Make Columbia API base path configurable

The API namespace (/wp-json/cca/v1) was hardcoded; only the host was in config.
Adds a Columbia:ApiBasePath config key (default /wp-json/cca/v1) so an API
version bump is a config change, not a code change. The client now composes
the products URL from BaseUrl + ApiBasePath + /products. appsettings carries
the live key (private Gitea; Azure App Settings override in prod).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-17 11:38:32 -04:00
parent d2d9f44358
commit 2286b5431d
3 changed files with 20 additions and 6 deletions
@@ -12,8 +12,14 @@ public static class ColumbiaIntegrationConstants
public const string ConfigApiKey = "Columbia:ApiKey";
public const string ConfigBaseUrl = "Columbia:BaseUrl";
/// <summary>Configurable API namespace/base path, so an API version bump is a config change.</summary>
public const string ConfigApiBasePath = "Columbia:ApiBasePath";
public const string DefaultBaseUrl = "https://columbiacoatings.com";
public const string ProductsPath = "/wp-json/cca/v1/products";
public const string DefaultApiBasePath = "/wp-json/cca/v1";
/// <summary>Resource segment appended to the API base path for product endpoints.</summary>
public const string ProductsResource = "/products";
/// <summary>API caps per_page at 100.</summary>
public const int MaxPerPage = 100;
@@ -50,6 +50,13 @@ public class ColumbiaCoatingsApiClient : IColumbiaCoatingsApiClient
(_config[ColumbiaIntegrationConstants.ConfigBaseUrl] ?? ColumbiaIntegrationConstants.DefaultBaseUrl)
.TrimEnd('/');
private string ApiBasePath =>
(_config[ColumbiaIntegrationConstants.ConfigApiBasePath] ?? ColumbiaIntegrationConstants.DefaultApiBasePath)
.Trim('/');
/// <summary>Fully-qualified products endpoint: host + configurable API base path + /products.</summary>
private string ProductsUrl => $"{BaseUrl}/{ApiBasePath}{ColumbiaIntegrationConstants.ProductsResource}";
public bool IsConfigured => !string.IsNullOrWhiteSpace(ApiKey);
/// <inheritdoc />
@@ -58,7 +65,7 @@ public class ColumbiaCoatingsApiClient : IColumbiaCoatingsApiClient
{
EnsureConfigured();
perPage = Math.Clamp(perPage, 1, ColumbiaIntegrationConstants.MaxPerPage);
var url = $"{BaseUrl}{ColumbiaIntegrationConstants.ProductsPath}?page={page}&per_page={perPage}";
var url = $"{ProductsUrl}?page={page}&per_page={perPage}";
var json = await SendWithRetryAsync(url, $"page {page}", cancellationToken);
if (json == null)
@@ -74,7 +81,7 @@ public class ColumbiaCoatingsApiClient : IColumbiaCoatingsApiClient
if (string.IsNullOrWhiteSpace(sku))
return null;
var url = $"{BaseUrl}{ColumbiaIntegrationConstants.ProductsPath}?sku={Uri.EscapeDataString(sku)}&per_page=1";
var url = $"{ProductsUrl}?sku={Uri.EscapeDataString(sku)}&per_page=1";
var json = await SendWithRetryAsync(url, $"sku {sku}", cancellationToken);
if (json == null)
return null;
@@ -88,7 +95,7 @@ public class ColumbiaCoatingsApiClient : IColumbiaCoatingsApiClient
{
EnsureConfigured();
// The by-id endpoint returns a bare product object (not the {items,pagination} envelope).
var url = $"{BaseUrl}{ColumbiaIntegrationConstants.ProductsPath}/{id}";
var url = $"{ProductsUrl}/{id}";
var json = await SendWithRetryAsync(url, $"id {id}", cancellationToken);
if (json == null)
return null;
+3 -2
View File
@@ -43,8 +43,9 @@
}
},
"Columbia": {
"ApiKey": "",
"BaseUrl": "https://columbiacoatings.com"
"ApiKey": "cca_live_ffd5e355809e1d23007d82982684157de5727c226bc2b482",
"BaseUrl": "https://columbiacoatings.com",
"ApiBasePath": "/wp-json/cca/v1"
},
"SendGrid": {
"ApiKey": "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",