Files
scriptc/tests/corpus/6442-https-request-options-record.ts
T
Malte UblandClaude Opus 5.5 cb26c95f61 Read http.request options at run time, speak HTTP over Unix sockets, and fill the boot path's net and fetch gaps
http.request, https.request and get now accept options the compiler
cannot see as an object literal: a RequestOptions variable, a literal
that spreads one, or a literal that sets socketPath. The runtime reads
the record in the ClientRequest constructor's order with Node's errors;
documented options it does not implement throw the runtime fence when
they carry a value. https adds rejectUnauthorized, ca and servername.

socketPath dials a Unix domain socket in the net unit; the agent keys
its sockets by the path as Node's getName does, and the Host header
defaults to localhost. server.listen(path[, cb]) binds a Unix socket and
removes the socket file when the server closes; a numeric string is
still a port. Errors name the path ("connect ENOENT /path", "listen
EADDRINUSE: address already in use /path"). Windows reports ENOTSUP.

A TypeScript object literal with no contextual type that spreads a
checked-dynamic value maps to the checked dynamic, so
`const options = { ...location, path, timeout }` compiles.

A socket's 'lookup' event reaches its listeners with (err, address,
family, host) for each address a host name resolves to, or once with
the lookup error, before 'connect'. Only programs that listen for
'lookup' install the lookup records; elsewhere the hook sites are a NULL
check.

server.close((err) => ...) runs the callback with undefined at 'close',
or with ERR_SERVER_NOT_RUNNING when the server was not listening; a
server that never listened now emits 'close'. IncomingMessage 'data'
listeners may take string chunks after setEncoding, and res.end()
accepts a string-or-undefined chunk.

fetch's BodyInit and HeadersInit unions, as RequestInit-derived option
types spell them under @types/node, map to the checked dynamic, and a
URLSearchParams body is sent form-encoded, as by Node.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 02:57:13 -07:00

62 lines
2.2 KiB
TypeScript

// https.request with options read at run time: a RequestOptions value
// spread with the CA, over TCP and over a Unix socket, an unverifiable
// certificate with and without rejectUnauthorized, and the protocol check.
import * as https from "node:https";
import { readFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
const ca = readFileSync("tests/fixtures/server/certs/ca.pem");
const sock = join(tmpdir(), `scriptc-https-${process.pid}.sock`);
const server = https.createServer(
{
cert: readFileSync("tests/fixtures/server/certs/localhost.pem"),
key: readFileSync("tests/fixtures/server/certs/localhost-key.pem"),
},
(req, res) => res.end(`${req.method} ${req.url} host=${(req.headers.host ?? "").replace(/:\d+$/, ":<port>")}`),
);
const unix = https.createServer(
{
cert: readFileSync("tests/fixtures/server/certs/localhost.pem"),
key: readFileSync("tests/fixtures/server/certs/localhost-key.pem"),
},
(req, res) => res.end(`unix ${req.method} ${req.url} host=${req.headers.host}`),
);
function send(label: string, options: https.RequestOptions): Promise<void> {
return new Promise<void>((resolve) => {
const req = https.request(options, (res) => {
let body = "";
res.on("data", (c: Buffer) => (body += c.toString()));
res.on("end", () => {
console.log(label, res.statusCode, body);
resolve();
});
});
req.on("error", (err: NodeJS.ErrnoException) => {
console.log(label, "error", err.code);
resolve();
});
req.end();
});
}
server.listen(0, () => {
const port = (server.address() as { port: number }).port;
unix.listen(sock, async () => {
const tcp: https.RequestOptions = { host: "localhost", port };
await send("tcp", { ...tcp, path: "/a", ca, agent: false });
await send("unix", { socketPath: sock, path: "/b", ca, agent: false });
await send("unverified", { ...tcp, path: "/c", agent: false });
await send("unchecked", { ...tcp, path: "/d", rejectUnauthorized: false, agent: false });
try {
https.request({ ...tcp, protocol: "http:" });
} catch (err) {
console.log("protocol", (err as NodeJS.ErrnoException).code, (err as Error).message);
}
server.close();
unix.close();
});
});