Repository: remix-run/react-router
File: packages/react-router-dev/vite/node-adapter.ts (TypeScript)

Code before:
    method: nodeReq.method,
    headers: fromNodeHeaders(nodeReq),
    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;

  // HTTP/2 doesn't support status messages (RFC7540 8.1.2.4)
  if (!nodeRes.req || nodeRes.req.httpVersionMajor < 2) {
    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();
  }

Review comment (suggestion):
Lets drop a link in here for easier lookup

```suggestion
  // HTTP/2 doesn't support status messages
  // https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.4
```

Code after:
    method: nodeReq.method,
    headers: fromNodeHeaders(nodeReq),
    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;

  // HTTP/2 doesn't support status messages
  // https://datatracker.ietf.org/doc/html/rfc7540#section-8.1.2.4
  if (!nodeRes.req || nodeRes.req.httpVersionMajor < 2) {
    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();