-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adapt superflare from remix → react-router
this required duplicating node-adapter.js and maintaining it within superflare-remix, because it’s no longer included in the published package’s dist/ directory. here’s a PR that exposes the (from|to)NodeRequest utilities that we depend on in the superflareDevProxyVitePlugin: remix-run/react-router#12774 if it gets merged, we can remove superflare-remix/node.adapter.ts and import those utils alongside cloudflareDevProxy note that i also needed to update superflare-remix’s tsconfig.json module and moduleResolution settings to get it to build without error (presumably due to changes between the published remix vs react-router packages
- Loading branch information
Showing
8 changed files
with
257 additions
and
2,882 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// https://github.com/remix-run/react-router/blob/main/packages/react-router-dev/vite/node-adapter.ts | ||
declare module "set-cookie-parser"; | ||
import type { IncomingHttpHeaders, ServerResponse } from "node:http"; | ||
import { once } from "node:events"; | ||
import { Readable } from "node:stream"; | ||
import { splitCookiesString } from "set-cookie-parser"; | ||
import { createReadableStreamFromReadable } from "@react-router/node"; | ||
import type * as Vite from "vite"; | ||
|
||
export type NodeRequestHandler = ( | ||
req: Vite.Connect.IncomingMessage, | ||
res: ServerResponse | ||
) => Promise<void>; | ||
|
||
function fromNodeHeaders(nodeHeaders: IncomingHttpHeaders): Headers { | ||
let headers = new Headers(); | ||
|
||
for (let [key, values] of Object.entries(nodeHeaders)) { | ||
if (values) { | ||
if (Array.isArray(values)) { | ||
for (let value of values) { | ||
headers.append(key, value); | ||
} | ||
} else { | ||
headers.set(key, values); | ||
} | ||
} | ||
} | ||
|
||
return headers; | ||
} | ||
|
||
// Based on `createRemixRequest` in packages/react-router-express/server.ts | ||
export function fromNodeRequest( | ||
nodeReq: Vite.Connect.IncomingMessage, | ||
nodeRes: ServerResponse<Vite.Connect.IncomingMessage> | ||
): Request { | ||
let origin = | ||
nodeReq.headers.origin && "null" !== nodeReq.headers.origin | ||
? nodeReq.headers.origin | ||
: `http://${nodeReq.headers.host}`; | ||
// Use `req.originalUrl` so React Router is aware of the full path | ||
invariant( | ||
nodeReq.originalUrl, | ||
"Expected `nodeReq.originalUrl` to be defined" | ||
); | ||
// @ts-expect-error this is a @react-router/dev file | ||
let url = new URL(nodeReq.originalUrl, origin); | ||
|
||
// Abort action/loaders once we can no longer write a response | ||
let controller: AbortController | null = new AbortController(); | ||
let init: RequestInit = { | ||
method: nodeReq.method, | ||
headers: fromNodeHeaders(nodeReq.headers), | ||
signal: controller.signal, | ||
}; | ||
|
||
// Abort action/loaders once we can no longer write a response iff we have | ||
// not yet sent a response (i.e., `close` without `finish`) | ||
// `finish` -> done rendering the response | ||
// `close` -> response can no longer be written to | ||
nodeRes.on("finish", () => (controller = null)); | ||
nodeRes.on("close", () => controller?.abort()); | ||
|
||
if (nodeReq.method !== "GET" && nodeReq.method !== "HEAD") { | ||
init.body = createReadableStreamFromReadable(nodeReq); | ||
(init as { duplex: "half" }).duplex = "half"; | ||
} | ||
|
||
return new Request(url.href, init); | ||
} | ||
|
||
// Adapted from solid-start's `handleNodeResponse`: | ||
// https://github.com/solidjs/solid-start/blob/7398163869b489cce503c167e284891cf51a6613/packages/start/node/fetch.js#L162-L185 | ||
export async function toNodeRequest(res: Response, nodeRes: ServerResponse) { | ||
nodeRes.statusCode = res.status; | ||
nodeRes.statusMessage = res.statusText; | ||
|
||
let cookiesStrings = []; | ||
|
||
for (let [name, value] of res.headers) { | ||
if (name === "set-cookie") { | ||
cookiesStrings.push(...splitCookiesString(value)); | ||
} else nodeRes.setHeader(name, value); | ||
} | ||
|
||
if (cookiesStrings.length) { | ||
nodeRes.setHeader("set-cookie", cookiesStrings); | ||
} | ||
|
||
if (res.body) { | ||
// https://github.com/microsoft/TypeScript/issues/29867 | ||
let responseBody = res.body as unknown as AsyncIterable<Uint8Array>; | ||
let readable = Readable.from(responseBody); | ||
readable.pipe(nodeRes); | ||
await once(readable, "end"); | ||
} else { | ||
nodeRes.end(); | ||
} | ||
} | ||
|
||
function invariant(value: any, message?: string) { | ||
if (value === false || value == null) { | ||
throw new Error(message); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.