From a58e60553636b36a39c9825d4aaafc1bdde38358 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Sun, 27 Sep 2026 02:18:02 +0000 Subject: [PATCH 1/2] http: add isValidHeaderName() and isValidHeaderValue() Add non-throwing counterparts of http.validateHeaderName() and http.validateHeaderValue() that return a boolean instead of throwing. Rejecting an invalid header with the existing validators costs a few microseconds, because an error object and its stack trace are created, compared to ~20ns for the boolean check. Userland HTTP implementations such as undici (fetch Headers, request options) therefore keep private copies of the token and field-value tables from _http_common. These new functions let them reuse the core implementation. isValidHeaderValue() accepts an optional `httpValidation` option ('strict' or 'relaxed') that has the same meaning as the option of the same name on http.createServer() and http.request(). Signed-off-by: James M Snell --- doc/api/http.md | 86 +++++++++++ lib/_http_outgoing.js | 44 +++++- lib/http.js | 4 + test/parallel/test-http-is-valid-header.js | 168 +++++++++++++++++++++ 4 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 test/parallel/test-http-is-valid-header.js diff --git a/doc/api/http.md b/doc/api/http.md index c4888f2bf660..5351b05eeaa9 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -4403,6 +4403,89 @@ request. Specifically, the `'error'` event will be emitted with an error with the message `'AbortError: The operation was aborted'`, the code `'ABORT_ERR'` and the `cause`, if one was provided. +## `http.isValidHeaderName(name)` + + + +* `name` {any} +* Returns: {boolean} + +Returns `true` if `name` is a valid HTTP header name (a non-empty string that +is an HTTP [token][]), and `false` otherwise. This is the same check that +[`http.validateHeaderName()`][] performs, but the result is returned instead of +an error being thrown, so it is suitable for use in hot paths where invalid +input is expected. + +HTTP methods are also tokens, so this function can validate them as well. + +```mjs +import { isValidHeaderName } from 'node:http'; + +console.log(isValidHeaderName('content-type')); // true +console.log(isValidHeaderName('X-Request-Id')); // true +console.log(isValidHeaderName('')); // false +console.log(isValidHeaderName('bad header')); // false +console.log(isValidHeaderName(42)); // false +``` + +```cjs +const { isValidHeaderName } = require('node:http'); + +console.log(isValidHeaderName('content-type')); // true +console.log(isValidHeaderName('X-Request-Id')); // true +console.log(isValidHeaderName('')); // false +console.log(isValidHeaderName('bad header')); // false +console.log(isValidHeaderName(42)); // false +``` + +## `http.isValidHeaderValue(value[, options])` + + + +* `value` {any} +* `options` {Object} + * `httpValidation` {string} Validation strictness, one of `'strict'` or + `'relaxed'`. These have the same meaning as the `httpValidation` option of + [`http.createServer()`][] and [`http.request()`][]. **Default:** `'strict'`. +* Returns: {boolean} + +Returns `true` if `value` is a valid HTTP header value, and `false` otherwise. +With the default options this is the same check that +[`http.validateHeaderValue()`][] performs, but the result is returned instead +of an error being thrown. + +`undefined` and symbols are never valid header values. Other non-string +values are converted to strings before being checked, as they are when passed +to [`outgoingMessage.setHeader(name, value)`][]. + +Passing an invalid `options` argument throws. + +```mjs +import { isValidHeaderValue } from 'node:http'; + +console.log(isValidHeaderValue('text/html')); // true +console.log(isValidHeaderValue(123)); // true +console.log(isValidHeaderValue(undefined)); // false +console.log(isValidHeaderValue('a\r\nb')); // false +console.log(isValidHeaderValue('a\x01b')); // false +console.log(isValidHeaderValue('a\x01b', { httpValidation: 'relaxed' })); // true +``` + +```cjs +const { isValidHeaderValue } = require('node:http'); + +console.log(isValidHeaderValue('text/html')); // true +console.log(isValidHeaderValue(123)); // true +console.log(isValidHeaderValue(undefined)); // false +console.log(isValidHeaderValue('a\r\nb')); // false +console.log(isValidHeaderValue('a\x01b')); // false +console.log(isValidHeaderValue('a\x01b', { httpValidation: 'relaxed' })); // true +``` + ## `http.validateHeaderName(name[, label])`