Skip to content

Commit 97837f6

Browse files
authored
feat(context): expose responseHeaders on EndpointContext (#131)
1 parent 2c6201c commit 97837f6

2 files changed

Lines changed: 47 additions & 0 deletions

File tree

packages/better-call/src/context.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,22 @@ export type EndpointContext<
148148
secret: string,
149149
options?: CookieOptions,
150150
) => Promise<string>;
151+
/**
152+
* Response headers
153+
*
154+
* The live `Headers` for the response being built in the current
155+
* request. Read it to inspect what has already been queued, e.g. to
156+
* avoid emitting a `Set-Cookie` twice or to check headers set by an
157+
* earlier handler in the chain.
158+
*
159+
* @example
160+
* ```ts
161+
* const alreadySet = ctx.responseHeaders
162+
* .getSetCookie()
163+
* .some((c) => c.startsWith("session="));
164+
* ```
165+
*/
166+
responseHeaders: Headers;
151167
/**
152168
* JSON
153169
*

packages/better-call/src/endpoint.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1097,3 +1097,34 @@ describe("onAPIError", () => {
10971097
expect(error?.status).toBe("UNAUTHORIZED");
10981098
});
10991099
});
1100+
1101+
describe("responseHeaders", () => {
1102+
it("exposes the live response headers accumulator inside the handler", async () => {
1103+
const endpoint = createEndpoint("/test", { method: "GET" }, async (ctx) => {
1104+
ctx.setCookie("session", "abc");
1105+
ctx.setHeader("x-custom", "1");
1106+
const setCookies = ctx.responseHeaders.getSetCookie();
1107+
const custom = ctx.responseHeaders.get("x-custom");
1108+
return { setCookies, custom };
1109+
});
1110+
const result = await endpoint();
1111+
expect(result.custom).toBe("1");
1112+
expect(result.setCookies).toHaveLength(1);
1113+
expect(result.setCookies[0]).toMatch(/^session=abc/);
1114+
});
1115+
1116+
it("lets a later handler step observe what an earlier one wrote", async () => {
1117+
const endpoint = createEndpoint("/test", { method: "GET" }, async (ctx) => {
1118+
ctx.setCookie("first", "v1");
1119+
const alreadySet = ctx.responseHeaders
1120+
.getSetCookie()
1121+
.some((c) => c.startsWith("first="));
1122+
if (!alreadySet) {
1123+
ctx.setCookie("first", "v2");
1124+
}
1125+
return { count: ctx.responseHeaders.getSetCookie().length };
1126+
});
1127+
const result = await endpoint();
1128+
expect(result.count).toBe(1);
1129+
});
1130+
});

0 commit comments

Comments
 (0)