From 4a47db72ae1a7af3e75314570a7a3917624a44ed Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Sat, 21 Mar 2026 12:12:14 -0700 Subject: [PATCH] =?UTF-8?q?fix(flags):=20SSE=20stream=20endpoint=20+=20cli?= =?UTF-8?q?ent=20=E2=80=94=20pass=20productId=20via=20query=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EventSource API cannot set custom headers, so the SSE /flags/stream endpoint and feature-flag-client were broken for streaming mode: - Server: accept productId and token from query string as fallback when x-product-id / authorization headers are absent - Client: pass productId (and optional auth token) as query params when constructing the EventSource URL --- packages/feature-flag-client/src/client.ts | 7 ++++++- services/platform-service/src/modules/flags/routes.ts | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/feature-flag-client/src/client.ts b/packages/feature-flag-client/src/client.ts index ba95e790..98c2fe1f 100644 --- a/packages/feature-flag-client/src/client.ts +++ b/packages/feature-flag-client/src/client.ts @@ -194,7 +194,12 @@ export function createFeatureFlagClient(config: FeatureFlagClientConfig): Featur return; } - const url = `${baseUrl}/flags/stream`; + const parts = [`productId=${encodeURIComponent(productId)}`]; + if (getAccessToken) { + const token = getAccessToken(); + if (token) parts.push(`token=${encodeURIComponent(token)}`); + } + const url = `${baseUrl}/flags/stream?${parts.join('&')}`; eventSource = new globalThis.EventSource(url); eventSource.onmessage = event => { diff --git a/services/platform-service/src/modules/flags/routes.ts b/services/platform-service/src/modules/flags/routes.ts index 7b4b7f7a..c04fc933 100644 --- a/services/platform-service/src/modules/flags/routes.ts +++ b/services/platform-service/src/modules/flags/routes.ts @@ -524,6 +524,14 @@ export async function flagRoutes(app: FastifyInstance) { // ── SSE stream ──────────────────────────────────────────────────────── app.get('/flags/stream', async (req, reply) => { + // EventSource cannot set custom headers, so accept productId + token from query string + const qs = req.query as { productId?: string; token?: string }; + if (qs.productId && !req.headers['x-product-id']) { + (req.headers as Record)['x-product-id'] = qs.productId; + } + if (qs.token && !req.headers['authorization']) { + (req.headers as Record)['authorization'] = `Bearer ${qs.token}`; + } const productId = getRequestProductId(req); reply.raw.writeHead(200, {