Skip to content

Commit

Permalink
[quick-edit] Partitioned cookies (#5016)
Browse files Browse the repository at this point in the history
  • Loading branch information
penalosa authored Feb 19, 2024
1 parent 88be4b8 commit 01e0846
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 24 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,8 @@
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
}
}
5 changes: 3 additions & 2 deletions fixtures/worker-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
"type:tests": "tsc -p ./tests/tsconfig.json"
},
"devDependencies": {
"wrangler": "workspace:*",
"@cloudflare/workers-tsconfig": "workspace:^",
"undici": "^5.28.3"
"undici": "^5.28.3",
"wrangler": "workspace:*"
},
"dependencies": {
"cookie": "^0.6.0",
"isomorphic-random-example": "workspace:^"
}
}
22 changes: 21 additions & 1 deletion fixtures/worker-app/src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import cookie from "cookie";
import { randomBytes } from "isomorphic-random-example";
import { now } from "./dep";
import { logErrors } from "./log";
Expand All @@ -15,10 +16,29 @@ export default {
async fetch(request) {
console.log("request log");

const { pathname, origin } = new URL(request.url);
const { pathname, origin, hostname, host } = new URL(request.url);
if (pathname === "/random") return new Response(hexEncode(randomBytes(8)));
if (pathname === "/error") throw new Error("Oops!");
if (pathname === "/redirect") return Response.redirect(`${origin}/foo`);
if (pathname === "/cookie")
return new Response("", {
headers: [
[
"Set-Cookie",
cookie.serialize("hello", "world", {
domain: hostname,
}),
],
[
"Set-Cookie",
cookie.serialize("hello2", "world2", {
domain: host,
secure: true,
}),
],
],
});

if (request.headers.get("X-Test-URL") !== null) {
return new Response(request.url);
}
Expand Down
11 changes: 11 additions & 0 deletions fixtures/worker-app/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,15 @@ describe("'wrangler dev' correctly renders pages", () => {
`http://${ip}:${port}/foo`
);
});

it("rewrites set-cookie headers to the hostname, not host", async ({
expect,
}) => {
const response = await fetch(`http://${ip}:${port}/cookie`);

expect(response.headers.getSetCookie()).toStrictEqual([
`hello=world; Domain=${ip}`,
`hello2=world2; Domain=${ip}; Secure`,
]);
});
});
6 changes: 3 additions & 3 deletions packages/edge-preview-authenticated-proxy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
"devDependencies": {
"@cloudflare/eslint-config-worker": "*",
"@cloudflare/workers-types": "^4.20230321.0",
"cookie": "^0.5.0",
"@types/cookie": "^0.6.0",
"cookie": "^0.6.0",
"promjs": "^0.4.2",
"toucan-js": "^3.1.0",
"wrangler": "workspace:*",
"@types/cookie": "^0.5.1"
"wrangler": "workspace:*"
}
}
1 change: 1 addition & 0 deletions packages/edge-preview-authenticated-proxy/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ async function updatePreviewToken(url: URL, env: Env, ctx: ExecutionContext) {
sameSite: "none",
httpOnly: true,
domain: url.hostname,
partitioned: true,
}),
},
});
Expand Down
16 changes: 8 additions & 8 deletions packages/edge-preview-authenticated-proxy/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ compatibility_date = "2023-01-01"
expect(
removeUUID(resp.headers.get("set-cookie") ?? "")
).toMatchInlineSnapshot(
'"token=00000000-0000-0000-0000-000000000000; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; SameSite=None"'
'"token=00000000-0000-0000-0000-000000000000; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; Partitioned; SameSite=None"'
);
tokenId = (resp.headers.get("set-cookie") ?? "")
.split(";")[0]
Expand All @@ -152,7 +152,7 @@ compatibility_date = "2023-01-01"
{
method: "GET",
headers: {
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; SameSite=None`,
cookie: `token=${tokenId}`,
},
}
);
Expand Down Expand Up @@ -183,7 +183,7 @@ compatibility_date = "2023-01-01"
expect(
removeUUID(resp.headers.get("set-cookie") ?? "")
).toMatchInlineSnapshot(
'"token=00000000-0000-0000-0000-000000000000; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; SameSite=None"'
'"token=00000000-0000-0000-0000-000000000000; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; Partitioned; SameSite=None"'
);
tokenId = (resp.headers.get("set-cookie") ?? "")
.split(";")[0]
Expand Down Expand Up @@ -218,7 +218,7 @@ compatibility_date = "2023-01-01"
{
method: "GET",
headers: {
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; SameSite=None`,
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; Partitioned; SameSite=None`,
},
}
);
Expand All @@ -237,7 +237,7 @@ compatibility_date = "2023-01-01"
{
method: "GET",
headers: {
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; SameSite=None`,
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; Partitioned; SameSite=None`,
},
redirect: "manual",
}
Expand All @@ -255,7 +255,7 @@ compatibility_date = "2023-01-01"
{
method: "PUT",
headers: {
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; SameSite=None`,
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; Partitioned; SameSite=None`,
},
redirect: "manual",
}
Expand All @@ -270,7 +270,7 @@ compatibility_date = "2023-01-01"
method: "PUT",
headers: {
"X-Custom-Header": "custom",
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; SameSite=None`,
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; Partitioned; SameSite=None`,
},
redirect: "manual",
}
Expand All @@ -284,7 +284,7 @@ compatibility_date = "2023-01-01"
{
method: "PUT",
headers: {
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; SameSite=None`,
cookie: `token=${tokenId}; Domain=random-data.preview.devprod.cloudflare.dev; HttpOnly; Secure; Partitioned; SameSite=None`,
},
redirect: "manual",
}
Expand Down
11 changes: 11 additions & 0 deletions packages/wrangler/templates/startDevWorker/ProxyWorker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ function insertLiveReloadScript(
* so that this proxy is transparent to the Client Browser and User Worker.
*/
function rewriteUrlRelatedHeaders(headers: Headers, from: URL, to: URL) {
const setCookie = headers.getAll("Set-Cookie");
headers.delete("Set-Cookie");
headers.forEach((value, key) => {
if (typeof value === "string" && value.includes(from.host)) {
headers.set(
Expand All @@ -312,4 +314,13 @@ function rewriteUrlRelatedHeaders(headers: Headers, from: URL, to: URL) {
);
}
});
for (const cookie of setCookie) {
headers.append(
"Set-Cookie",
cookie.replace(
new RegExp(`Domain=${from.hostname}($|;|,)`),
`Domain=${to.hostname}$1`
)
);
}
}
31 changes: 21 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 01e0846

Please sign in to comment.