Skip to content

Commit c4517a9

Browse files
steipeteVectorPeak
andcommitted
fix(signal): preserve base URL path prefixes
Co-authored-by: VectorPeak <[email protected]>
1 parent 3f976a9 commit c4517a9

2 files changed

Lines changed: 58 additions & 1 deletion

File tree

extensions/signal/src/client.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,24 @@ describe("signalRpcRequest", () => {
9292
expect(result).toEqual({ version: "0.13.22" });
9393
});
9494

95+
it("preserves path-prefixed base URLs for RPC requests", async () => {
96+
const serverUrl = await withSignalServer(async (req, res) => {
97+
expect(req.method).toBe("POST");
98+
expect(req.url).toBe("/signal/api/v1/rpc");
99+
expect(JSON.parse(await readRequestBody(req))).toMatchObject({
100+
method: "version",
101+
});
102+
res.writeHead(200, { "Content-Type": "application/json" });
103+
res.end(JSON.stringify({ jsonrpc: "2.0", result: { version: "0.13.22" }, id: "test-id" }));
104+
});
105+
106+
await expect(
107+
signalRpcRequest<{ version: string }>("version", undefined, {
108+
baseUrl: `${serverUrl}/signal/`,
109+
}),
110+
).resolves.toEqual({ version: "0.13.22" });
111+
});
112+
95113
it("throws a wrapped error when RPC response JSON is malformed", async () => {
96114
const baseUrl = await withSignalServer((_req, res) => {
97115
res.writeHead(502, { "Content-Type": "text/plain" });
@@ -256,6 +274,21 @@ describe("signalCheck", () => {
256274
await expect(signalCheck(baseUrl)).resolves.toEqual({ ok: true, status: 204, error: null });
257275
});
258276

277+
it("preserves path-prefixed base URLs for health checks", async () => {
278+
const serverUrl = await withSignalServer((req, res) => {
279+
expect(req.method).toBe("GET");
280+
expect(req.url).toBe("/signal/api/v1/check");
281+
res.writeHead(204);
282+
res.end();
283+
});
284+
285+
await expect(signalCheck(`${serverUrl}/signal`)).resolves.toEqual({
286+
ok: true,
287+
status: 204,
288+
error: null,
289+
});
290+
});
291+
259292
it("returns an HTTP status failure for unhealthy checks", async () => {
260293
const baseUrl = await withSignalServer((_req, res) => {
261294
res.writeHead(503);
@@ -290,6 +323,25 @@ describe("streamSignalEvents", () => {
290323
expect(events).toEqual([{ id: "42", event: "message", data: '{"group":true}' }]);
291324
});
292325

326+
it("preserves path-prefixed base URLs for event streams", async () => {
327+
type StreamEvent = Parameters<Parameters<typeof streamSignalEvents>[0]["onEvent"]>[0];
328+
const events: StreamEvent[] = [];
329+
const serverUrl = await withSignalServer((req, res) => {
330+
expect(req.url).toBe("/signal/api/v1/events?account=%2B15555550123");
331+
expect(req.headers.accept).toBe("text/event-stream");
332+
res.writeHead(200, { "Content-Type": "text/event-stream" });
333+
res.end('id: 42\nevent: message\ndata: {"group":true}\n\n');
334+
});
335+
336+
await streamSignalEvents({
337+
baseUrl: `${serverUrl}/signal`,
338+
account: "+15555550123",
339+
onEvent: (event) => events.push(event),
340+
});
341+
342+
expect(events).toEqual([{ id: "42", event: "message", data: '{"group":true}' }]);
343+
});
344+
293345
it("propagates receive-handler failures to the stream", async () => {
294346
const appendError = new Error("durable append failed");
295347
const baseUrl = await withSignalServer((_req, res) => {

extensions/signal/src/client.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,12 @@ function parseSignalBaseUrl(url: string): URL {
6868
}
6969

7070
function resolveSignalEndpointUrl(baseUrl: string, pathname: string): URL {
71-
return new URL(pathname, parseSignalBaseUrl(baseUrl));
71+
const parsed = parseSignalBaseUrl(baseUrl);
72+
const basePath = parsed.pathname.endsWith("/") ? parsed.pathname : `${parsed.pathname}/`;
73+
parsed.pathname = `${basePath}${pathname.replace(/^\/+/, "")}`;
74+
parsed.search = "";
75+
parsed.hash = "";
76+
return parsed;
7277
}
7378

7479
function parseSignalRpcResponse<T>(text: string, status: number): SignalRpcResponse<T> {

0 commit comments

Comments
 (0)