Skip to content

Commit 3643ff3

Browse files
authored
Write event.response.headers to returned Responses (#2011)
1 parent 139defd commit 3643ff3

3 files changed

Lines changed: 72 additions & 3 deletions

File tree

apps/tests/src/e2e/api-call.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,18 @@ test.describe("api calls", () => {
55
const response = await fetch("http://localhost:3000/api/text-plain");
66
expect(await response.text()).toBe("test");
77
});
8+
9+
test("should include headers from both event and returned request", async () => {
10+
const okResp = await fetch("http://localhost:3000/api/header-merging?status=ok");
11+
expect(okResp.headers.get("Set-Cookie")).toBeTruthy();
12+
expect(okResp.headers.get("x-event-header")).toBe("value");
13+
expect(okResp.headers.get("x-return-header")).toBe("value");
14+
expect(okResp.headers.get("x-shared-header")).toBe("event");
15+
16+
const redirectResp = await fetch("http://localhost:3000/api/header-merging?status=redirect", { redirect: "manual" });
17+
expect(redirectResp.headers.get("Set-Cookie")).toBeTruthy();
18+
expect(redirectResp.headers.get("x-event-header")).toBe("value");
19+
expect(redirectResp.headers.get("x-return-header")).toBe("value");
20+
expect(redirectResp.headers.get("x-shared-header")).toBe("event");
21+
})
822
});
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { getRequestURL, setHeader, useSession } from "@solidjs/start/http";
2+
3+
export async function GET() {
4+
const url = getRequestURL();
5+
6+
const s = await useSession({ password: "0".repeat(32) });
7+
await s.update(d => ({count: (d.count || 0) + 1}))
8+
9+
setHeader("x-event-header", "value");
10+
setHeader("x-shared-header", "event");
11+
12+
if(url.searchParams.get("status") === "redirect") {
13+
return new Response(null, {
14+
status: 301,
15+
headers: {
16+
location: "http://::/abc",
17+
"x-return-header": "value",
18+
"x-shared-header": "return"
19+
}
20+
})
21+
} else {
22+
return new Response(null, {
23+
headers: {
24+
"x-return-header": "value",
25+
"x-shared-header": "return"
26+
}
27+
})
28+
}
29+
}

packages/start/src/server/handler.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ export function createBaseHandler(
3838
if (pathname.startsWith(serverFunctionTest)) {
3939
const serverFnResponse = await handleServerFunction(e);
4040

41-
if (serverFnResponse instanceof Response) return serverFnResponse;
41+
if (serverFnResponse instanceof Response)
42+
return produceResponseWithEventHeaders(serverFnResponse);
4243

4344
return new Response(serverFnResponse as any, {
4445
headers: e.res.headers,
@@ -56,7 +57,11 @@ export function createBaseHandler(
5657
// @ts-expect-error
5758
sharedConfig.context = { event };
5859
const res = await fn!(event);
59-
if (res !== undefined) return res;
60+
if (res !== undefined) {
61+
if(res instanceof Response) return produceResponseWithEventHeaders(res)
62+
63+
return res;
64+
}
6065
if (event.request.method !== "GET") {
6166
throw new Error(
6267
`API handler for ${event.request.method} "${event.request.url}" did not return a response.`,
@@ -130,7 +135,7 @@ export function createBaseHandler(
130135

131136
const app = new H3();
132137

133-
app.use(handler);
138+
app.use(handler);
134139

135140
return app;
136141
}
@@ -222,3 +227,24 @@ function handleStreamCompleteRedirect(context: PageEvent) {
222227
to && write(`<script>window.location="${to}"</script>`);
223228
};
224229
}
230+
231+
function produceResponseWithEventHeaders(res: Response) {
232+
const event = getRequestEvent()!;
233+
234+
let ret = res;
235+
236+
// Response.redirect returns an immutable value, so we clone on any redirect just in case
237+
if(300 <= res.status && res.status < 400) {
238+
ret = new Response(res.body, {
239+
status: res.status,
240+
statusText: res.statusText,
241+
headers: Object.fromEntries(res.headers.entries())
242+
});
243+
}
244+
245+
for(const [name, value] of event.response.headers) {
246+
ret.headers.set(name, value);
247+
}
248+
249+
return ret
250+
}

0 commit comments

Comments
 (0)