From cdfb1c5c25ccc03fbe5a8efea79961340b59f9d9 Mon Sep 17 00:00:00 2001 From: CharlieHelps Date: Sat, 8 Nov 2025 16:43:47 +0000 Subject: [PATCH] Fix HTTP client database path encoding --- packages/gel/src/utils.ts | 3 ++- packages/gel/test/client.test.ts | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/packages/gel/src/utils.ts b/packages/gel/src/utils.ts index 505b22eea..025923846 100644 --- a/packages/gel/src/utils.ts +++ b/packages/gel/src/utils.ts @@ -98,7 +98,8 @@ export async function getAuthenticatedFetch( const protocol = tlsSecurity === "insecure" ? "http" : "https"; const baseUrl = `${protocol}://${address[0]}:${address[1]}`; - const databaseUrl = `${baseUrl}/db/${database}/${basePath ?? ""}`; + const encodedDatabase = encodeURIComponent(database); + const databaseUrl = `${baseUrl}/db/${encodedDatabase}/${basePath ?? ""}`; if (!token && config.password != null) { token = await httpSCRAMAuth(baseUrl, config.user, config.password); diff --git a/packages/gel/test/client.test.ts b/packages/gel/test/client.test.ts index 3f8ab7af5..61bea2306 100644 --- a/packages/gel/test/client.test.ts +++ b/packages/gel/test/client.test.ts @@ -2344,6 +2344,46 @@ if (getAvailableFeatures().has("binary-over-http")) { fetchConn.rawParse(Language.EDGEQL, `select 1`, Options.defaults()), ).rejects.toThrow(AuthenticationError); }); + + test("getAuthenticatedFetch encodes database path segment", async () => { + const originalFetch = globalThis.fetch; + + const fetchMock = jest.fn(async () => + ({ + ok: true, + status: 200, + statusText: "OK", + headers: new Headers(), + arrayBuffer: async () => new ArrayBuffer(0), + }) as any, + ); + + (globalThis as any).fetch = fetchMock; + + const config = { + address: ["localhost", 5656], + tlsSecurity: "insecure", + database: "preview/pr-662", + secretKey: "test-secret", + user: "test-user", + } as any; + + const authenticatedFetch = await getAuthenticatedFetch( + config, + async () => "token", + ); + + await authenticatedFetch("", {}); + + expect(fetchMock).toHaveBeenCalledTimes(1); + + const [urlArg] = fetchMock.mock.calls[0]; + const url = typeof urlArg === "string" ? new URL(urlArg) : urlArg; + + expect(url.pathname).toBe("/db/preview%2Fpr-662/"); + + (globalThis as any).fetch = originalFetch; + }); } if (getGelVersion().major >= 5) {