Skip to content

Commit 7187ea8

Browse files
authored
fix(react): normalize event stream URLs
Normalize the React event-stream base URL consistently with evaluation requests so trailing slashes do not request a double-slash path. Include regression coverage and an Unreleased entry. Co-authored-by: Sebastien Tardif <sebtardif@ncf.ca>
1 parent 23582fe commit 7187ea8

3 files changed

Lines changed: 16 additions & 1 deletion

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ All notable changes to Krillswitch are documented in this file.
66

77
### Fixed
88

9+
- Strip a trailing slash from the React event-stream URL so a base URL ending in `/` connects to `/v1/stream`. Thanks @SebTardif.
910
- Bound GitHub organization membership checks to five seconds during sign-in, including response-body reads, while preserving cached membership on network failure. Thanks @SebTardif.
1011
- Abort webhook deliveries after two seconds, record timeout status, and keep unattempted entries queued without delaying other subscribers. Thanks @SebTardif.
1112
- Abort CLI API requests and response-body reads after a new 30-second default deadline, report timeout errors clearly, and support `KRILLSWITCH_TIMEOUT_MS` overrides (`0` restores unlimited waits). Thanks @SebTardif.

‎packages/react/src/krillswitch.test.tsx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,20 @@ describe("stream", () => {
712712
);
713713
});
714714

715+
it("strips a trailing slash from the stream URL the same way eval does", async () => {
716+
fetchMock.mockResolvedValue(evalResponse({ souls: false }));
717+
render(
718+
<FeatureFlagProvider evalKey={EVAL_KEY} baseUrl={`${BASE_URL}/`} stream>
719+
<SoulsProbe />
720+
</FeatureFlagProvider>,
721+
);
722+
await waitFor(() => expect(FakeEventSource.instances.length).toBe(1));
723+
expect(FakeEventSource.instances[0]?.url).toBe(
724+
`${BASE_URL}/v1/stream?key=${encodeURIComponent(EVAL_KEY)}`,
725+
);
726+
expect(FakeEventSource.instances[0]?.url).not.toContain("//v1/stream");
727+
});
728+
715729
it("closes the stream on unmount and never opens one without the option", async () => {
716730
fetchMock.mockResolvedValue(evalResponse({ souls: false }));
717731
const withStream = render(

‎packages/react/src/krillswitch.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ function createClient<M extends FlagManifest>(
276276
let eventSource: EventSource | null = null;
277277
if (stream && typeof EventSource !== "undefined") {
278278
eventSource = new EventSource(
279-
`${baseUrl}/v1/stream?key=${encodeURIComponent(evalKey)}`,
279+
`${baseUrl.replace(/\/+$/, "")}/v1/stream?key=${encodeURIComponent(evalKey)}`,
280280
);
281281
eventSource.addEventListener("change", () => void refresh());
282282
}

0 commit comments

Comments
 (0)