Files
scriptc/tests/corpus/5562-https-verify-errors.ts
T
Chris Tate f7362fc386 Match Node's http keep-alive, header and framing behavior
- server.close() closes idle keep-alive connections, and every open
  connection closes after keepAliveTimeout + keepAliveTimeoutBuffer, so a
  closed server whose clients keep their connections no longer stays up.
  The Keep-Alive response header gives keepAliveTimeout in whole seconds
  and is omitted when it is 0.
- A client request through an Agent with neither keepAlive nor a finite
  maxSockets sends Connection: close.
- "socket hang up" and "aborted" errors carry code ECONNRESET, a client
  head over the header limit fails with HPE_HEADER_OVERFLOW, and TLS
  verification failures carry their openssl code.
- Outgoing header values keep the type they were set with: getHeader and
  getHeaders answer numbers and arrays, appendHeader turns an existing
  value into an array, and setHeader(name, string[]) writes one line per
  element.
- Repeated incoming header fields join with ", " ("; " for cookie),
  Node's single-value fields keep the first value, and set-cookie reads
  as an array under @types/node, on server requests and client responses.
  Fetch reads response headers line by line.
- Expect: 100-continue is answered with 100 Continue before 'request';
  other expectations answer 417.
- HEAD requests and 1xx/204/304 responses send no body or length header,
  and HTTP/1.0 requests without a set length get an unframed body and
  Connection: close.
- The 16 KiB maxHeaderSize applies to the request target plus header
  names and values (431 on the server).
- https.Agent TLS options are refused by name instead of being dropped,
  and server.address() lowers for @types/node's
  string | AddressInfo | null result.

Corpus 5555-5563 and the node-types http-headers-address fixture cover
each case.
2026-10-15 13:06:33 -05:00

58 lines
2.4 KiB
TypeScript

// https.request verifies the server certificate against `ca`. A failed
// verification reports Node's message and openssl code, and
// rejectUnauthorized: false skips the check. Requests through an
// https.Agent take their TLS options from the request.
import * as https from "node:https";
import { readFileSync } from "node:fs";
const cert = readFileSync("tests/fixtures/server/certs/localhost.pem");
const key = readFileSync("tests/fixtures/server/certs/localhost-key.pem");
const ca = readFileSync("tests/fixtures/server/certs/ca.pem");
const server = https.createServer({ key, cert }, (req, res) => {
res.end(`hello ${req.url}`);
});
function settle(label: string, start: (resolve: (s: string) => void) => void): Promise<void> {
return new Promise<string>((resolve) => start(resolve)).then((s) => console.log(label, s));
}
server.listen(0, "127.0.0.1", async () => {
const port = (server.address() as { port: number }).port;
await settle("ca", (resolve) => {
const req = https.request({ host: "localhost", port, path: "/ca", ca: ca }, (res) => {
let body = "";
res.on("data", (c: Buffer) => (body += c.toString()));
res.on("end", () => resolve(`${res.statusCode} ${body}`));
});
req.on("error", (err: NodeJS.ErrnoException) => resolve(`error ${err.code} ${err.message}`));
req.end();
});
await settle("noca", (resolve) => {
const req = https.request({ host: "localhost", port, path: "/noca" }, (res) => {
res.resume();
res.on("end", () => resolve(`${res.statusCode}`));
});
req.on("error", (err: NodeJS.ErrnoException) => resolve(`error ${err.code} ${err.message}`));
req.end();
});
await settle("insecure", (resolve) => {
const req = https.request({ host: "localhost", port, path: "/insecure", rejectUnauthorized: false }, (res) => {
res.resume();
res.on("end", () => resolve(`${res.statusCode}`));
});
req.on("error", (err: NodeJS.ErrnoException) => resolve(`error ${err.code} ${err.message}`));
req.end();
});
await settle("agent", (resolve) => {
const agent = new https.Agent({ maxSockets: 2 });
const req = https.request({ host: "localhost", port, path: "/agent", agent: agent, ca: ca }, (res) => {
res.resume();
res.on("end", () => resolve(`${res.statusCode}`));
});
req.on("error", (err: NodeJS.ErrnoException) => resolve(`error ${err.code} ${err.message}`));
req.end();
});
server.close(() => console.log("closed"));
});