Skip to content

Commit

Permalink
fix: handle multiple "Set-Cookie" headers in Vite dev (#7843)
Browse files Browse the repository at this point in the history
Co-authored-by: Mark Dalgleish <[email protected]>
  • Loading branch information
nickprinsloo and markdalgleish authored Nov 2, 2023
1 parent 33c64cb commit e3675c5
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 1 deletion.
5 changes: 5 additions & 0 deletions .changeset/silent-rice-march.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@remix-run/dev": patch
---

Handle multiple "Set-Cookie" headers in Vite dev server
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@
- ngtrthinh169TPC
- ni554n
- nicholaschiang
- nickprinsloo
- nicksrandall
- nickytonline
- niconiahi
Expand Down
61 changes: 61 additions & 0 deletions integration/vite-dev-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,54 @@ test.describe("Vite dev", () => {
);
}
`,
"app/routes/set-cookies.tsx": js`
import { LoaderFunction } from "@remix-run/node";
export const loader: LoaderFunction = () => {
const headers = new Headers();
headers.append(
"Set-Cookie",
"first=one; Domain=localhost; Path=/; SameSite=Lax"
);
headers.append(
"Set-Cookie",
"second=two; Domain=localhost; Path=/; SameSite=Lax"
);
headers.append(
"Set-Cookie",
"third=three; Domain=localhost; Path=/; SameSite=Lax"
);
headers.set("location", "http://localhost:${devPort}/get-cookies");
const response = new Response(null, {
headers,
status: 302,
});
return response;
};
`,
"app/routes/get-cookies.tsx": js`
import { json, LoaderFunctionArgs } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react"
export const loader = ({ request }: LoaderFunctionArgs) => json({cookies: request.headers.get("Cookie")});
export default function IndexRoute() {
const { cookies } = useLoaderData<typeof loader>();
return (
<div id="get-cookies">
<h2 data-title>Get Cookies</h2>
<p data-cookies>{cookies}</p>
</div>
);
}
`,
},
});

Expand Down Expand Up @@ -141,6 +189,19 @@ test.describe("Vite dev", () => {
await expect(hmrStatus).toHaveText("HMR updated: yes");
await expect(input).toHaveValue("stateful");
});

test("handles multiple set-cookie headers", async ({ page }) => {
await page.goto(`http://localhost:${devPort}/set-cookies`, {
waitUntil: "networkidle",
});

// Ensure we redirected
expect(new URL(page.url()).pathname).toBe("/get-cookies");

await expect(page.locator("#get-cookies [data-cookies]")).toHaveText(
"first=one; second=two; third=three"
);
});
});

let bufferize = (stream: Readable): (() => string) => {
Expand Down
10 changes: 9 additions & 1 deletion packages/remix-dev/vite/node/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,16 +167,24 @@ function createRequest(req: IncomingMessage): Request {
return new NodeRequest(url.href, init);
}

// Adapted from more recent version of `handleNodeResponse`:
// https://github.com/solidjs/solid-start/blob/7398163869b489cce503c167e284891cf51a6613/packages/start/node/fetch.js#L162-L185
async function handleNodeResponse(webRes: Response, res: ServerResponse) {
res.statusCode = webRes.status;
res.statusMessage = webRes.statusText;

let cookiesStrings = [];

for (let [name, value] of webRes.headers) {
if (name === "set-cookie") {
res.setHeader(name, splitCookiesString(value));
cookiesStrings.push(...splitCookiesString(value));
} else res.setHeader(name, value);
}

if (cookiesStrings.length) {
res.setHeader("set-cookie", cookiesStrings);
}

if (webRes.body) {
let readable = Readable.from(webRes.body);
readable.pipe(res);
Expand Down

0 comments on commit e3675c5

Please sign in to comment.