diff --git a/libs/providers/go-feature-flag-web/README.md b/libs/providers/go-feature-flag-web/README.md index 39339776a..1bcb49f56 100644 --- a/libs/providers/go-feature-flag-web/README.md +++ b/libs/providers/go-feature-flag-web/README.md @@ -29,6 +29,9 @@ const evaluationCtx: EvaluationContext = { const goFeatureFlagWebProvider = new GoFeatureFlagWebProvider({ endpoint: endpoint, + customHeadeers: { + 'User-Agent': "my-app/1.0.0", + }, // ... }, logger); @@ -54,6 +57,7 @@ client.addHandler(ProviderEvents.ConfigurationChanged, () => { //... }); | endpoint | string | | endpoint is the URL where your GO Feature Flag server is located. | | apiTimeout | number | 0 = no timeout | (optional) timeout is the time in millisecond we wait for an answer from the server. | | apiKey | string | | (optional) If GO Feature Flag is configured to authenticate the requests, you should provide an API Key to the provider. Please ask the administrator of the relay proxy to provide an API Key. | +| customHeaders | object | | (optional) custom headers to be sent for every HTTP request. | | websocketRetryInitialDelay | number | 100 | (optional) initial delay in millisecond to wait before retrying to connect the websocket | | websocketRetryDelayMultiplier | number | 2 | (optional) multiplier of websocketRetryInitialDelay after each failure _(example: 1st connection retry will be after 100ms, second after 200ms, third after 400ms ...)_ | | websocketMaxRetries | number | 10 | (optional) maximum number of retries before considering the websocket unreachable | diff --git a/libs/providers/go-feature-flag-web/src/lib/controller/goff-api.spec.ts b/libs/providers/go-feature-flag-web/src/lib/controller/goff-api.spec.ts index 30421b5ed..1d6737605 100644 --- a/libs/providers/go-feature-flag-web/src/lib/controller/goff-api.spec.ts +++ b/libs/providers/go-feature-flag-web/src/lib/controller/goff-api.spec.ts @@ -15,6 +15,10 @@ describe('Collect Data API', () => { endpoint: 'https://gofeatureflag.org', apiTimeout: 1000, apiKey: '123456', + customHeaders: { + 'User-Agent': 'goff-web/1.0.0', + Authorization: 'Bearer foo', + }, }; const goff = new GoffApiController(options); await goff.collectData( @@ -37,6 +41,7 @@ describe('Collect Data API', () => { 'Content-Type': 'application/json', Accept: 'application/json', Authorization: `Bearer ${options.apiKey}`, + 'User-Agent': 'goff-web/1.0.0', }); expect(fetchMock.lastOptions()?.body).toEqual( JSON.stringify({ @@ -62,6 +67,9 @@ describe('Collect Data API', () => { const options: GoFeatureFlagWebProviderOptions = { endpoint: 'https://gofeatureflag.org', apiTimeout: 1000, + customHeaders: { + 'User-Agent': 'goff-web/2.0.0', + }, }; const goff = new GoffApiController(options); await goff.collectData( @@ -83,6 +91,7 @@ describe('Collect Data API', () => { expect(fetchMock.lastOptions()?.headers).toEqual({ 'Content-Type': 'application/json', Accept: 'application/json', + 'User-Agent': 'goff-web/2.0.0', }); expect(fetchMock.lastOptions()?.body).toEqual( JSON.stringify({ diff --git a/libs/providers/go-feature-flag-web/src/lib/controller/goff-api.ts b/libs/providers/go-feature-flag-web/src/lib/controller/goff-api.ts index 5261f1faa..9bf1bf88b 100644 --- a/libs/providers/go-feature-flag-web/src/lib/controller/goff-api.ts +++ b/libs/providers/go-feature-flag-web/src/lib/controller/goff-api.ts @@ -42,6 +42,10 @@ export class GoffApiController { Accept: 'application/json', }; + if (this.options.customHeaders) { + Object.assign(headers, this.options.customHeaders); + } + if (this.options.apiKey) { headers['Authorization'] = `Bearer ${this.options.apiKey}`; } diff --git a/libs/providers/go-feature-flag-web/src/lib/go-feature-flag-web-provider.spec.ts b/libs/providers/go-feature-flag-web/src/lib/go-feature-flag-web-provider.spec.ts index 9c27840c1..cde6afe7f 100644 --- a/libs/providers/go-feature-flag-web/src/lib/go-feature-flag-web-provider.spec.ts +++ b/libs/providers/go-feature-flag-web/src/lib/go-feature-flag-web-provider.spec.ts @@ -322,6 +322,10 @@ describe('GoFeatureFlagWebProvider', () => { apiTimeout: 1000, maxRetries: 1, apiKey: 'my-api-key', + customHeaders: { + 'User-Agent': 'goff-web/3.0.0', + Authorization: 'Bearer foo', + }, }, logger, ); @@ -338,6 +342,7 @@ describe('GoFeatureFlagWebProvider', () => { const headers = lastCall[1]?.headers as never; expect(headers).not.toBeUndefined(); expect(headers['Authorization']).toBe('Bearer my-api-key'); + expect(headers['User-Agent']).toBe('goff-web/3.0.0'); return; } expect(true).toBe(false); diff --git a/libs/providers/go-feature-flag-web/src/lib/go-feature-flag-web-provider.ts b/libs/providers/go-feature-flag-web/src/lib/go-feature-flag-web-provider.ts index b4a3dfd86..8285ffde6 100644 --- a/libs/providers/go-feature-flag-web/src/lib/go-feature-flag-web-provider.ts +++ b/libs/providers/go-feature-flag-web/src/lib/go-feature-flag-web-provider.ts @@ -44,6 +44,8 @@ export class GoFeatureFlagWebProvider implements Provider { private readonly _apiTimeout: number; // apiKey is the key used to identify your request in GO Feature Flag private readonly _apiKey: string | undefined; + // customHeaders to be sent for every HTTP request. + private readonly _customHeaders: Record | undefined; // initial delay in millisecond to wait before retrying to connect private readonly _retryInitialDelay; // multiplier of _retryInitialDelay after each failure @@ -68,6 +70,7 @@ export class GoFeatureFlagWebProvider implements Provider { this._retryDelayMultiplier = options.retryDelayMultiplier || 2; this._maxRetries = options.maxRetries || 10; this._apiKey = options.apiKey; + this._customHeaders = options.customHeaders; this._disableDataCollection = options.disableDataCollection || false; this._collectorManager = new CollectorManager(options, logger); @@ -321,6 +324,7 @@ export class GoFeatureFlagWebProvider implements Provider { 'Content-Type': 'application/json', Accept: 'application/json', // we had the authorization header only if we have an API Key + ...(this._customHeaders || {}), ...(this._apiKey ? { Authorization: `Bearer ${this._apiKey}` } : {}), }, body: JSON.stringify(request), diff --git a/libs/providers/go-feature-flag-web/src/lib/model.ts b/libs/providers/go-feature-flag-web/src/lib/model.ts index 729cf03d6..9bcafa17f 100644 --- a/libs/providers/go-feature-flag-web/src/lib/model.ts +++ b/libs/providers/go-feature-flag-web/src/lib/model.ts @@ -45,6 +45,9 @@ export interface GoFeatureFlagWebProviderOptions { // Default: null apiKey?: string; + // customHeaders (optional) custom headers to be sent for every HTTP request. + customHeaders?: Record; + // initial delay in millisecond to wait before retrying to connect to GO Feature Flag (websocket and API) // Default: 100 ms retryInitialDelay?: number;