diff --git a/libs/providers/flagd/README.md b/libs/providers/flagd/README.md index 1506cf229..b1a3b405e 100644 --- a/libs/providers/flagd/README.md +++ b/libs/providers/flagd/README.md @@ -38,6 +38,7 @@ Options can be defined in the constructor or as environment variables. Construct | selector | FLAGD_SOURCE_SELECTOR | string | - | | | cache | FLAGD_CACHE | string | lru | lru, disabled | | maxCacheSize | FLAGD_MAX_CACHE_SIZE | int | 1000 | | +| serviceAuthority | FLAGD_SERVICE_AUTHORITY | string | - | rpc, in-process | #### Resolver type-specific Defaults diff --git a/libs/providers/flagd/src/lib/configuration.spec.ts b/libs/providers/flagd/src/lib/configuration.spec.ts index cd766356f..dac19c503 100644 --- a/libs/providers/flagd/src/lib/configuration.spec.ts +++ b/libs/providers/flagd/src/lib/configuration.spec.ts @@ -31,6 +31,7 @@ describe('Configuration', () => { const resolverType = 'in-process'; const selector = 'app=weather'; const offlineFlagSourcePath = '/tmp/flags.json'; + const serviceAuthority = 'test-service2'; process.env['FLAGD_HOST'] = host; process.env['FLAGD_PORT'] = `${port}`; @@ -41,6 +42,7 @@ describe('Configuration', () => { process.env['FLAGD_SOURCE_SELECTOR'] = `${selector}`; process.env['FLAGD_RESOLVER'] = `${resolverType}`; process.env['FLAGD_OFFLINE_FLAG_SOURCE_PATH'] = offlineFlagSourcePath; + process.env['FLAGD_SERVICE_AUTHORITY'] = serviceAuthority; expect(getConfig()).toStrictEqual({ host, @@ -52,6 +54,7 @@ describe('Configuration', () => { resolverType, selector, offlineFlagSourcePath, + serviceAuthority, }); }); @@ -64,6 +67,7 @@ describe('Configuration', () => { cache: 'lru', resolverType: 'rpc', selector: '', + serviceAuthority: '', }; process.env['FLAGD_HOST'] = 'override'; diff --git a/libs/providers/flagd/src/lib/configuration.ts b/libs/providers/flagd/src/lib/configuration.ts index cab759e40..b91bf8eb3 100644 --- a/libs/providers/flagd/src/lib/configuration.ts +++ b/libs/providers/flagd/src/lib/configuration.ts @@ -68,6 +68,13 @@ export interface Config { * @default 1000 */ maxCacheSize?: number; + + /** + * The target host (authority) when routing requests through a proxy (e.g. Envoy) + * + * @default '' + */ + serviceAuthority?: string; } export type FlagdProviderOptions = Partial; @@ -94,6 +101,7 @@ enum ENV_VAR { FLAGD_SOURCE_SELECTOR = 'FLAGD_SOURCE_SELECTOR', FLAGD_RESOLVER = 'FLAGD_RESOLVER', FLAGD_OFFLINE_FLAG_SOURCE_PATH = 'FLAGD_OFFLINE_FLAG_SOURCE_PATH', + FLAGD_SERVICE_AUTHORITY = 'FLAGD_SERVICE_AUTHORITY', } const getEnvVarConfig = (): Partial => ({ @@ -124,6 +132,9 @@ const getEnvVarConfig = (): Partial => ({ ...(process.env[ENV_VAR.FLAGD_OFFLINE_FLAG_SOURCE_PATH] && { offlineFlagSourcePath: process.env[ENV_VAR.FLAGD_OFFLINE_FLAG_SOURCE_PATH], }), + ...(process.env[ENV_VAR.FLAGD_SERVICE_AUTHORITY] && { + serviceAuthority: process.env[ENV_VAR.FLAGD_SERVICE_AUTHORITY], + }), }); export function getConfig(options: FlagdProviderOptions = {}) { diff --git a/libs/providers/flagd/src/lib/service/in-process/grpc/grpc-fetch.ts b/libs/providers/flagd/src/lib/service/in-process/grpc/grpc-fetch.ts index fd791f72c..6b12dbfef 100644 --- a/libs/providers/flagd/src/lib/service/in-process/grpc/grpc-fetch.ts +++ b/libs/providers/flagd/src/lib/service/in-process/grpc/grpc-fetch.ts @@ -1,4 +1,4 @@ -import { ClientReadableStream, ServiceError, credentials } from '@grpc/grpc-js'; +import { ClientReadableStream, ServiceError, credentials, ClientOptions } from '@grpc/grpc-js'; import { Logger } from '@openfeature/core'; import { GeneralError } from '@openfeature/server-sdk'; import { FlagSyncServiceClient, SyncFlagsRequest, SyncFlagsResponse } from '../../../../proto/ts/flagd/sync/v1/sync'; @@ -28,13 +28,21 @@ export class GrpcFetch implements DataFetch { private _isConnected = false; constructor(config: Config, syncServiceClient?: FlagSyncServiceClient, logger?: Logger) { - const { host, port, tls, socketPath, selector } = config; + const { host, port, tls, socketPath, selector, serviceAuthority } = config; + + let clientOptions: ClientOptions | undefined; + if (serviceAuthority) { + clientOptions = { + 'grpc.default_authority': serviceAuthority, + }; + } this._syncClient = syncServiceClient ? syncServiceClient : new FlagSyncServiceClient( socketPath ? `unix://${socketPath}` : `${host}:${port}`, tls ? credentials.createSsl() : credentials.createInsecure(), + clientOptions, ); this._logger = logger;