diff --git a/CHANGELOG.md b/CHANGELOG.md index 969d12d3bca..72a9219fb36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1 +1,2 @@ - Add warning when a developer is using yarn@2 PnP (#2198) +- Fixes incorrect URLs reported inside emulated HTTPS functions (#1862). diff --git a/src/emulator/functionsEmulator.ts b/src/emulator/functionsEmulator.ts index f4b1deff1be..c0b0018c153 100644 --- a/src/emulator/functionsEmulator.ts +++ b/src/emulator/functionsEmulator.ts @@ -1064,13 +1064,22 @@ export class FunctionsEmulator implements EmulatorInstance { ); } + // To match production behavior we need to drop the path prefix + // req.url = /:projectId/:region/:trigger_name/* + const url = new URL(`${req.protocol}://${req.hostname}${req.url}`); + const path = `${url.pathname}${url.search}`.replace( + `/${this.args.projectId}/us-central1/${triggerId}`, + "" + ); + // We do this instead of just 302'ing because many HTTP clients don't respect 302s so it may // cause unexpected situations - not to mention CORS troubles and this enables us to use // a socketPath (IPC socket) instead of consuming yet another port which is probably faster as well. + this.logger.log("DEBUG", `[functions] Got req.url=${req.url}, mapping to path=${path}`); const runtimeReq = http.request( { method, - path: req.url || "/", + path, headers: req.headers, socketPath: worker.lastArgs.frb.socketPath, }, diff --git a/src/emulator/functionsEmulatorRuntime.ts b/src/emulator/functionsEmulatorRuntime.ts index 43e673b73eb..9ccd843edcc 100644 --- a/src/emulator/functionsEmulatorRuntime.ts +++ b/src/emulator/functionsEmulatorRuntime.ts @@ -850,10 +850,7 @@ async function processHTTPS(frb: FunctionsRuntimeBundle, trigger: EmulatedTrigge functionRouter.all("*", handler); - ephemeralServer.use( - [`/${frb.projectId}/${frb.triggerId}`, `/${frb.projectId}/:region/${frb.triggerId}`], - functionRouter - ); + ephemeralServer.use([`/`, `/*`], functionRouter); logDebug(`Attempting to listen to socketPath: ${socketPath}`); const instance = ephemeralServer.listen(socketPath, () => { diff --git a/src/test/emulators/functionsEmulator.spec.ts b/src/test/emulators/functionsEmulator.spec.ts index 973dbed27ee..71f41b4b4bd 100644 --- a/src/test/emulators/functionsEmulator.spec.ts +++ b/src/test/emulators/functionsEmulator.spec.ts @@ -203,13 +203,43 @@ describe("FunctionsEmulator-Hub", () => { }); }).timeout(TIMEOUT_LONG); - it("should rewrite req.baseUrl to show /:project_id/:region/:trigger_id", async () => { + it("should return the correct url, baseUrl, originalUrl for the root route", async () => { useFunctions(() => { require("firebase-admin").initializeApp(); return { function_id: require("firebase-functions").https.onRequest( (req: express.Request, res: express.Response) => { - res.json({ baseUrl: req.baseUrl }); + res.json({ + url: req.url, + baseUrl: req.baseUrl, + originalUrl: req.originalUrl, + }); + } + ), + }; + }); + + await supertest(functionsEmulator.createHubServer()) + .get("/fake-project-id/us-central1/function_id") + .expect(200) + .then((res) => { + expect(res.body.url).to.eq("/"); + expect(res.body.baseUrl).to.eq(""); + expect(res.body.originalUrl).to.eq("/"); + }); + }).timeout(TIMEOUT_LONG); + + it("should return the correct url, baseUrl, originalUrl for a subroute", async () => { + useFunctions(() => { + require("firebase-admin").initializeApp(); + return { + function_id: require("firebase-functions").https.onRequest( + (req: express.Request, res: express.Response) => { + res.json({ + url: req.url, + baseUrl: req.baseUrl, + originalUrl: req.originalUrl, + }); } ), }; @@ -219,7 +249,9 @@ describe("FunctionsEmulator-Hub", () => { .get("/fake-project-id/us-central1/function_id/sub/route/a") .expect(200) .then((res) => { - expect(res.body.baseUrl).to.eq("/fake-project-id/us-central1/function_id"); + expect(res.body.url).to.eq("/sub/route/a"); + expect(res.body.baseUrl).to.eq(""); + expect(res.body.originalUrl).to.eq("/sub/route/a"); }); }).timeout(TIMEOUT_LONG); diff --git a/src/test/emulators/functionsEmulatorRuntime.spec.ts b/src/test/emulators/functionsEmulatorRuntime.spec.ts index 8f6752d21be..e313b00cbb3 100644 --- a/src/test/emulators/functionsEmulatorRuntime.spec.ts +++ b/src/test/emulators/functionsEmulatorRuntime.spec.ts @@ -57,7 +57,7 @@ function invokeRuntimeWithFunctions( async function callHTTPSFunction( worker: RuntimeWorker, frb: FunctionsRuntimeBundle, - options: { headers?: { [key: string]: string } } = {}, + options: { path?: string; headers?: { [key: string]: string } } = {}, requestData?: string ): Promise { await worker.waitForSocketReady(); @@ -67,7 +67,7 @@ async function callHTTPSFunction( } const socketPath = worker.lastArgs.frb.socketPath; - const path = `/${frb.projectId}/us-central1/${frb.triggerId}`; + const path = options.path || "/"; const res = await new Promise((resolve, reject) => { const req = request(