Skip to content

Commit b682cf7

Browse files
authored
Fix cookie parse with "Expire=" (#230)
* fix: handle comma from Expire cookie
1 parent 353b377 commit b682cf7

File tree

3 files changed

+64
-6
lines changed

3 files changed

+64
-6
lines changed

packages/open-next/src/adapters/event-mapper.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
} from "aws-lambda";
1010

1111
import { debug } from "./logger.js";
12+
import { parseCookies } from "./util.js";
1213

1314
export type InternalEvent = {
1415
readonly type: "v1" | "v2" | "cf";
@@ -205,15 +206,10 @@ function convertToApiGatewayProxyResultV2(
205206
headers[key] = Array.isArray(value) ? value.join(", ") : value.toString();
206207
});
207208

208-
let cookies = result.headers["set-cookie"];
209-
// AWS cookies are in a single `set-cookie` string, delimited by a comma
210-
if (cookies && typeof cookies === "string") {
211-
cookies = cookies.split(",").map((c) => c.trim());
212-
}
213209
const response: APIGatewayProxyResultV2 = {
214210
statusCode: result.statusCode,
215211
headers,
216-
cookies: cookies as string[],
212+
cookies: parseCookies(result.headers["set-cookie"]),
217213
body: result.body,
218214
isBase64Encoded: result.isBase64Encoded,
219215
};

packages/open-next/src/adapters/util.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,16 @@ export function unescapeRegex(str: string) {
116116

117117
return path;
118118
}
119+
120+
// AWS cookies are in a single `set-cookie` string, delimited by a comma
121+
export function parseCookies(
122+
cookies?: string | string[],
123+
): string[] | undefined {
124+
if (!cookies) return;
125+
126+
if (typeof cookies === "string") {
127+
return cookies.split(/(?<!Expires=\w+),/i).map((c) => c.trim());
128+
}
129+
130+
return cookies;
131+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { parseCookies } from "../../open-next/src/adapters/util";
2+
3+
describe("adapter utils", () => {
4+
describe("parseCookies", () => {
5+
it("returns undefined if cookies is empty", () => {
6+
const cookies = parseCookies("");
7+
expect(cookies).toBeUndefined();
8+
});
9+
it("returns undefined if no cookies", () => {
10+
const cookies = parseCookies();
11+
expect(cookies).toBeUndefined();
12+
});
13+
it("parse single cookie", () => {
14+
const cookies = parseCookies(
15+
"cookie1=value1; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; Path=/",
16+
);
17+
expect(cookies).toEqual([
18+
"cookie1=value1; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; Path=/",
19+
]);
20+
});
21+
it("parse multiple cookies", () => {
22+
// NOTE: expires is lower case but still works
23+
const cookies = parseCookies(
24+
"cookie1=value1; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; Path=/, cookie2=value2; HttpOnly; Secure",
25+
);
26+
expect(cookies).toEqual([
27+
"cookie1=value1; expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; Path=/",
28+
"cookie2=value2; HttpOnly; Secure",
29+
]);
30+
});
31+
it("return if cookies is already an array", () => {
32+
const cookies = parseCookies([
33+
"cookie1=value1; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; Path=/",
34+
]);
35+
expect(cookies).toEqual([
36+
"cookie1=value1; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; Secure; Path=/",
37+
]);
38+
});
39+
it("parses w/o Expire", () => {
40+
const cookies = parseCookies(
41+
"cookie1=value1; HttpOnly; Secure; Path=/, cookie2=value2; HttpOnly=false; Secure=True; Domain=example.com; Path=/api",
42+
);
43+
expect(cookies).toEqual([
44+
"cookie1=value1; HttpOnly; Secure; Path=/",
45+
"cookie2=value2; HttpOnly=false; Secure=True; Domain=example.com; Path=/api",
46+
]);
47+
});
48+
});
49+
});

0 commit comments

Comments
 (0)