Skip to content

Commit ba0b2a2

Browse files
feat: Support apiKey for GO Feature Flag relay proxy v1.7.0 (#310)
Co-authored-by: Michael Beemer <[email protected]>
1 parent 2936df3 commit ba0b2a2

File tree

4 files changed

+59
-14
lines changed

4 files changed

+59
-14
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { ErrorCode, OpenFeatureError } from '@openfeature/js-sdk'
2+
3+
// Unauthorized is an error send when the provider do an unauthorized call to the relay proxy.
4+
export class Unauthorized extends OpenFeatureError {
5+
code: ErrorCode
6+
7+
constructor(message: string) {
8+
super(message)
9+
Object.setPrototypeOf(this, Unauthorized.prototype)
10+
this.code = ErrorCode.GENERAL
11+
}
12+
}

libs/providers/go-feature-flag/src/lib/go-feature-flag-provider.spec.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import MockAdapter from 'axios-mock-adapter';
1212
import { ProxyNotReady } from './errors/proxyNotReady';
1313
import { ProxyTimeout } from './errors/proxyTimeout';
1414
import { UnknownError } from './errors/unknownError';
15+
import { Unauthorized } from './errors/unauthorized';
1516
import { GoFeatureFlagProvider } from './go-feature-flag-provider';
1617
import { GoFeatureFlagProxyResponse } from './model';
1718

@@ -80,7 +81,7 @@ describe('GoFeatureFlagProvider', () => {
8081
expect(result.errorCode).toEqual(ErrorCode.PARSE_ERROR)
8182
})
8283
});
83-
84+
8485
it('unknown error codes should return GENERAL code', async () => {
8586
const flagName = 'random-other-other-flag';
8687
const targetingKey = 'user-key';
@@ -132,6 +133,22 @@ describe('GoFeatureFlagProvider', () => {
132133
);
133134
});
134135
});
136+
it('should throw an error if invalid api key is propvided', async () => {
137+
const flagName = 'unauthorized';
138+
const targetingKey = 'user-key';
139+
const dns = `${endpoint}v1/feature/${flagName}/eval`;
140+
141+
axiosMock.onPost(dns).reply(401, {} as GoFeatureFlagProxyResponse<string>);
142+
143+
await goff
144+
.resolveStringEvaluation(flagName, 'sdk-default', { targetingKey })
145+
.catch((err) => {
146+
expect(err).toBeInstanceOf(Unauthorized);
147+
expect(err.message).toEqual(
148+
'invalid token used to contact GO Feature Flag relay proxy instance'
149+
);
150+
});
151+
});
135152
});
136153

137154
describe('resolveBooleanEvaluation', () => {

libs/providers/go-feature-flag/src/lib/go-feature-flag-provider.ts

+23-13
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,20 @@ import {
88
StandardResolutionReasons,
99
TypeMismatchError,
1010
} from '@openfeature/js-sdk';
11-
import axios from 'axios';
11+
import axios, { AxiosRequestConfig } from 'axios';
1212
import { transformContext } from './context-transformer';
1313
import { ProxyNotReady } from './errors/proxyNotReady';
1414
import { ProxyTimeout } from './errors/proxyTimeout';
1515
import { UnknownError } from './errors/unknownError';
16+
import { Unauthorized } from './errors/unauthorized';
1617
import {
1718
GoFeatureFlagProviderOptions,
1819
GoFeatureFlagProxyRequest,
1920
GoFeatureFlagProxyResponse,
2021
GoFeatureFlagUser,
2122
} from './model';
2223

24+
2325
// GoFeatureFlagProvider is the official Open-feature provider for GO Feature Flag.
2426
export class GoFeatureFlagProvider implements Provider {
2527
metadata = {
@@ -30,10 +32,13 @@ export class GoFeatureFlagProvider implements Provider {
3032
private endpoint: string;
3133
// timeout in millisecond before we consider the request as a failure
3234
private timeout: number;
35+
// apiKey contains the token to use while calling GO Feature Flag relay proxy
36+
private apiKey?: string;
3337

3438
constructor(options: GoFeatureFlagProviderOptions) {
3539
this.timeout = options.timeout || 0; // default is 0 = no timeout
3640
this.endpoint = options.endpoint;
41+
this.apiKey = options.apiKey;
3742
}
3843

3944
/**
@@ -149,7 +154,7 @@ export class GoFeatureFlagProvider implements Provider {
149154
* @throws {ProxyTimeout} When the HTTP call is timing out
150155
* @throws {UnknownError} When an unknown error occurs
151156
* @throws {TypeMismatchError} When the type of the variation is not the one expected
152-
* @throws {FlagNotFoundError} When the flag does not exists
157+
* @throws {FlagNotFoundError} When the flag does not exist
153158
*/
154159
async resolveEvaluationGoFeatureFlagProxy<T>(
155160
flagKey: string,
@@ -165,19 +170,24 @@ export class GoFeatureFlagProvider implements Provider {
165170

166171
let apiResponseData: GoFeatureFlagProxyResponse<T>;
167172
try {
168-
const response = await axios.post<GoFeatureFlagProxyResponse<T>>(
169-
endpointURL.toString(),
170-
request,
171-
{
172-
headers: {
173-
'Content-Type': 'application/json',
174-
Accept: 'application/json',
175-
},
176-
timeout: this.timeout,
177-
}
178-
);
173+
const reqConfig: AxiosRequestConfig = {
174+
headers: {
175+
'Content-Type': 'application/json',
176+
Accept: 'application/json',
177+
},
178+
timeout: this.timeout,
179+
};
180+
181+
if (this.apiKey) {
182+
reqConfig.headers?.put('Authorization', `Bearer ${this.apiKey}`);
183+
}
184+
185+
const response = await axios.post<GoFeatureFlagProxyResponse<T>>(endpointURL.toString(), request, reqConfig);
179186
apiResponseData = response.data;
180187
} catch (error) {
188+
if (axios.isAxiosError(error) && error.response?.status == 401) {
189+
throw new Unauthorized('invalid token used to contact GO Feature Flag relay proxy instance');
190+
}
181191
// Impossible to contact the relay-proxy
182192
if (
183193
axios.isAxiosError(error) &&

libs/providers/go-feature-flag/src/lib/model.ts

+6
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ export interface GoFeatureFlagProxyResponse<T> {
4747
export interface GoFeatureFlagProviderOptions {
4848
endpoint: string;
4949
timeout?: number; // in millisecond
50+
51+
// apiKey (optional) If the relay proxy is configured to authenticate the requests, you should provide
52+
// an API Key to the provider. Please ask the administrator of the relay proxy to provide an API Key.
53+
// (This feature is available only if you are using GO Feature Flag relay proxy v1.7.0 or above)
54+
// Default: null
55+
apiKey?: string;
5056
}
5157

5258
// GOFeatureFlagResolutionReasons allows to extends resolution reasons

0 commit comments

Comments
 (0)