Title: doc: `tls.connect` supports `requestOCSP` option but it is undocumented · Issue #61042 · nodejs/node · GitHub
Open Graph Title: doc: `tls.connect` supports `requestOCSP` option but it is undocumented · Issue #61042 · nodejs/node
X Title: doc: `tls.connect` supports `requestOCSP` option but it is undocumented · Issue #61042 · nodejs/node
Description: What is the problem? According to the documentation, the requestOCSP option is supported by the new tls.TLSSocket() constructor, but tls.connect() does not list requestOCSP as a supported option. However, in practice, tls.connect() does ...
Open Graph Description: What is the problem? According to the documentation, the requestOCSP option is supported by the new tls.TLSSocket() constructor, but tls.connect() does not list requestOCSP as a supported option. H...
X Description: What is the problem? According to the documentation, the requestOCSP option is supported by the new tls.TLSSocket() constructor, but tls.connect() does not list requestOCSP as a supported option. H...
Opengraph URL: https://github.com/nodejs/node/issues/61042
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"doc: `tls.connect` supports `requestOCSP` option but it is undocumented","articleBody":"### What is the problem?\n\nAccording to the documentation, the `requestOCSP` option is supported by the\n`new tls.TLSSocket()` constructor, but **`tls.connect()` does not list\n`requestOCSP` as a supported option**.\n\nHowever, in practice, `tls.connect()` *does* accept and honor the\n`requestOCSP` option.\n\nThis creates a documentation inconsistency: users relying on `tls.connect()`\ncannot discover that OCSP stapling can be requested, even though it works.\n\n### What is expected?\n\nDocument that `tls.connect()` supports the `requestOCSP` option, and describe its effect, in the same way it is documented for `new tls.TLSSocket()`.\n\n### Affected docs\n\nhttps://nodejs.org/api/tls.html#tlsconnectoptions-callback\n\n---\n\n### Observed behavior\n\nWhen passing `{ requestOCSP: true }` to `tls.connect()`, it causes the client to request\nOCSP stapling during the TLS handshake:\n\n- The server emits an `OCSPRequest` event\n- The client receives an `OCSPResponse` event\n\nWhen `requestOCSP` is `false`, no OCSP request is made and no response\nis received.\n\nThe behavior is reproducible and matches the documented behavior of `new tls.TLSSocket()`.\n\n\u003cdetails\u003e\n\u003csummary\u003eTest code\u003c/summary\u003e\n\n```sh\n# generate server.key\nopenssl genrsa -out server.key 2048\n# generate server.crt\nopenssl req -x509 -new -nodes \\\n -key server.key \\\n -sha256 \\\n -days 1 \\\n -out server.crt \\\n -subj \"/CN=ocsp.example.test\" \\\n -addext \"subjectAltName=DNS:ocsp.example.test\"\n```\n\nAfter that, execute the following typescript in the same directory:\n```ts\nimport * as assert from \"node:assert\";\nimport * as fs from \"node:fs\";\nimport { describe, it } from \"node:test\";\nimport * as tls from \"node:tls\";\n\nconst certPem = fs.readFileSync(\"server.crt\");\nconst keyPem = fs.readFileSync(\"server.key\");\n\nconst domain = \"ocsp.example.test\";\n\ndeclare module \"node:tls\" {\n interface ConnectionOptions {\n requestOCSP?: boolean;\n }\n}\n\nasync function withTlsServer(\n onListening: (server: tls.Server, port: number) =\u003e Promise\u003cvoid\u003e,\n options?: tls.TlsOptions,\n) {\n await using server = tls.createServer({\n cert: certPem,\n key: keyPem,\n minVersion: \"TLSv1.2\",\n maxVersion: \"TLSv1.2\",\n ...options,\n });\n\n await new Promise\u003cvoid\u003e((resolve, reject) =\u003e {\n server.once(\"error\", reject);\n server.listen(0, \"127.0.0.1\", resolve);\n });\n\n const address = server.address();\n assert.ok(address \u0026\u0026 typeof address === \"object\", \"server did not start\");\n\n server.on(\"secureConnection\", (socket) =\u003e {\n socket.on(\"OCSPResponse\", () =\u003e {\n throw new Error(\"Server socket should not receive OCSPResponse events\");\n });\n });\n\n await onListening(server, address.port);\n}\n\nfunction connectWithRequestOCSP(port: number, requestOCSP: boolean) {\n return new Promise\u003c(Buffer | null)[]\u003e((resolve, reject) =\u003e {\n const tlsSocket = tls.connect(\n {\n port,\n host: \"127.0.0.1\",\n servername: domain,\n minVersion: \"TLSv1.2\",\n maxVersion: \"TLSv1.2\",\n rejectUnauthorized: false,\n requestOCSP,\n },\n () =\u003e {\n tlsSocket.end();\n },\n );\n\n const ocspResponses: Array\u003cBuffer | null\u003e = [];\n tlsSocket.on(\"OCSPResponse\", response =\u003e ocspResponses.push(response));\n tlsSocket.once(\"error\", reject);\n tlsSocket.setTimeout(3_000, () =\u003e tlsSocket.destroy(new Error(\"TLS handshake timeout\")));\n tlsSocket.once(\"close\", () =\u003e resolve(ocspResponses));\n });\n}\n\nfunction randomBytes(length: number): Buffer\u003cArrayBuffer\u003e {\n const buffer = Buffer.alloc(length);\n crypto.getRandomValues(buffer);\n return buffer;\n}\nfunction createOcspRequestCounter(server: tls.Server, randomBuffer: Buffer) {\n let count = 0;\n server.on(\"OCSPRequest\", (_certificate, _issuer, callback) =\u003e {\n count += 1;\n callback(null, randomBuffer);\n });\n return () =\u003e count;\n}\n\ndescribe(\"tls OCSP behavior\", () =\u003e {\n describe(\"connect\", () =\u003e {\n it(\"requests OCSP stapling when requestOCSP is true\", async () =\u003e\n await withTlsServer(async (server, port) =\u003e {\n const randomBuffer = randomBytes(16);\n const ocspRequestCounter = createOcspRequestCounter(server, randomBuffer);\n const ocspResponses = await connectWithRequestOCSP(port, true);\n assert.strictEqual(ocspRequestCounter(), 1);\n assert.deepEqual(ocspResponses, [randomBuffer]);\n }));\n\n it(\"does not request OCSP stapling when requestOCSP is false\", async () =\u003e\n await withTlsServer(async (server, port) =\u003e {\n const randomBuffer = randomBytes(16);\n const ocspRequestCounter = createOcspRequestCounter(server, randomBuffer);\n const ocspResponses = await connectWithRequestOCSP(port, false);\n assert.strictEqual(ocspRequestCounter(), 0);\n assert.deepEqual(ocspResponses, []);\n }));\n });\n describe(\"createServer\", () =\u003e {\n it(\"requestOCSP option has no effect\", async () =\u003e {\n for (const requestOCSP of [true, false]) {\n await withTlsServer(\n async (server, port) =\u003e {\n const randomBuffer = randomBytes(16);\n const ocspRequestCounter = createOcspRequestCounter(server, randomBuffer);\n const ocspResponses = await connectWithRequestOCSP(port, true);\n assert.strictEqual(ocspRequestCounter(), 1);\n assert.deepEqual(ocspResponses, [randomBuffer]);\n },\n // @ts-expect-error Testing undocumented option\n { requestOCSP },\n );\n }\n });\n });\n});\n```\n\u003c/details\u003e\n","author":{"url":"https://github.com/ikeyan","@type":"Person","name":"ikeyan"},"datePublished":"2025-12-13T06:13:23.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/61042/node/issues/61042"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:ba9dfe33-3b25-500d-5312-d43d2140c32e |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | E7EE:2F266A:0E36:10DC:6A4C106B |
| html-safe-nonce | ddceb28fc67860c95a883cd0296d3ed084fdb05fe58c3efb67af8402027d32a1 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJFN0VFOjJGMjY2QTowRTM2OjEwREM6NkE0QzEwNkIiLCJ2aXNpdG9yX2lkIjoiMTQyNjczNzI0MjE1MjExMjIzNSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 4b283d37815eb2bae1c4440d96a76c6ad18f0037999f86fdba27a3e0f68e8f8f |
| hovercard-subject-tag | issue:3725574495 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/nodejs/node/61042/issue_layout |
| twitter:image | https://opengraph.githubassets.com/b11a3714437d324b1547f7c87f83b070f017cc3e53bd1fff245a4eed7e485e85/nodejs/node/issues/61042 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/b11a3714437d324b1547f7c87f83b070f017cc3e53bd1fff245a4eed7e485e85/nodejs/node/issues/61042 |
| og:image:alt | What is the problem? According to the documentation, the requestOCSP option is supported by the new tls.TLSSocket() constructor, but tls.connect() does not list requestOCSP as a supported option. H... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | ikeyan |
| hostname | github.com |
| expected-hostname | github.com |
| None | 0ccfc9e5281bfe12e38a4d632dc422843e4d5b6757917f7efda2f6567d72fea9 |
| turbo-cache-control | no-preview |
| go-import | github.com/nodejs/node git https://github.com/nodejs/node.git |
| octolytics-dimension-user_id | 9950313 |
| octolytics-dimension-user_login | nodejs |
| octolytics-dimension-repository_id | 27193779 |
| octolytics-dimension-repository_nwo | nodejs/node |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 27193779 |
| octolytics-dimension-repository_network_root_nwo | nodejs/node |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 18812876666a23a0912556e224383baa4c84cf8e |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width