diff --git a/apps/web/src/cloudflare/workspace-share-router.test.ts b/apps/web/src/cloudflare/workspace-share-router.test.ts index 9149ed9631..4d4570f694 100644 --- a/apps/web/src/cloudflare/workspace-share-router.test.ts +++ b/apps/web/src/cloudflare/workspace-share-router.test.ts @@ -97,3 +97,29 @@ test("removes workspace proxy headers when passing through platform hosts", asyn assert.equal(response.status, 200); assert.equal(fetchMock.mock.callCount(), 1); }); + +for (const [location, expected] of [ + [ + "https://anarlog.netlify.app/app/?view=compact#notes", + "https://fastrepl.anarlog.so/app/?view=compact#notes", + ], + ["/auth/?flow=web", "https://fastrepl.anarlog.so/auth/?flow=web"], + ["https://accounts.google.com/auth", "https://accounts.google.com/auth"], +]) { + test(`preserves the browser destination for redirect ${location}`, async (t) => { + const fetchMock = t.mock.method( + globalThis, + "fetch", + async () => new Response(null, { status: 308, headers: { location } }), + ); + + const response = await worker.fetch( + new Request("https://fastrepl.anarlog.so/app"), + { WORKSPACE_SHARE_PROXY_SECRET: "test-secret" }, + ); + + assert.equal(response.status, 308); + assert.equal(response.headers.get("location"), expected); + assert.equal(fetchMock.mock.callCount(), 1); + }); +} diff --git a/apps/web/src/cloudflare/workspace-share-router.ts b/apps/web/src/cloudflare/workspace-share-router.ts index 99b63235af..c75dc04125 100644 --- a/apps/web/src/cloudflare/workspace-share-router.ts +++ b/apps/web/src/cloudflare/workspace-share-router.ts @@ -61,6 +61,22 @@ export default { return new Response("Sharing domain unavailable", { status: 503 }); } - return fetch(originRequest); + const response = await fetch(originRequest); + const location = response.headers.get("location"); + if (response.status < 300 || response.status >= 400 || !location) { + return response; + } + + const redirectUrl = new URL(location, originRequest.url); + if (redirectUrl.origin !== APP_ORIGIN) return response; + + redirectUrl.host = incomingUrl.host; + const headers = new Headers(response.headers); + headers.set("location", redirectUrl.toString()); + return new Response(response.body, { + status: response.status, + statusText: response.statusText, + headers, + }); }, };