From d0115f14f66b06d6fef05d114fdf093991456a50 Mon Sep 17 00:00:00 2001 From: simov Date: Mon, 8 Mar 2021 21:27:49 +0200 Subject: [PATCH] http: add http.ClientRequest.getRawHeaderNames() Fixes: https://github.com/nodejs/node/issues/37641 PR-URL: https://github.com/nodejs/node/pull/37660 Reviewed-By: Matteo Collina Reviewed-By: Benjamin Gruenbaum Reviewed-By: Rich Trott --- doc/api/deprecations.md | 1 + doc/api/http.md | 18 ++++++++++++++++++ lib/_http_outgoing.js | 19 +++++++++++++++++++ test/parallel/test-http-mutable-headers.js | 15 ++++++++++++++- 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/doc/api/deprecations.md b/doc/api/deprecations.md index 769d15516d99b5..3f78df5646ebbe 100644 --- a/doc/api/deprecations.md +++ b/doc/api/deprecations.md @@ -1340,6 +1340,7 @@ The `http` module `OutgoingMessage.prototype._headers` and the public methods (e.g. `OutgoingMessage.prototype.getHeader()`, `OutgoingMessage.prototype.getHeaders()`, `OutgoingMessage.prototype.getHeaderNames()`, +`OutgoingMessage.prototype.getRawHeaderNames()`, `OutgoingMessage.prototype.hasHeader()`, `OutgoingMessage.prototype.removeHeader()`, `OutgoingMessage.prototype.setHeader()`) for working with outgoing headers. diff --git a/doc/api/http.md b/doc/api/http.md index dc24ff05278541..a50bd445c17faa 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -756,6 +756,24 @@ const cookie = request.getHeader('Cookie'); // 'cookie' is of type string[] ``` +### `request.getRawHeaderNames()` + + +* Returns: {string[]} + +Returns an array containing the unique names of the current outgoing raw +headers. Header names are returned with their exact casing being set. + +```js +request.setHeader('Foo', 'bar'); +request.setHeader('Set-Cookie', ['foo=bar', 'bar=baz']); + +const headerNames = request.getRawHeaderNames(); +// headerNames === ['Foo', 'Set-Cookie'] +``` + ### `request.maxHeadersCount` * {number} **Default:** `2000` diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js index 5173dc8e9e46ac..7736c31c4d41a8 100644 --- a/lib/_http_outgoing.js +++ b/lib/_http_outgoing.js @@ -22,10 +22,12 @@ 'use strict'; const { + Array, ArrayIsArray, ObjectCreate, ObjectDefineProperty, ObjectKeys, + ObjectValues, ObjectPrototypeHasOwnProperty, ObjectSetPrototypeOf, MathFloor, @@ -588,6 +590,23 @@ OutgoingMessage.prototype.getHeaderNames = function getHeaderNames() { }; +// Returns an array of the names of the current outgoing raw headers. +OutgoingMessage.prototype.getRawHeaderNames = function getRawHeaderNames() { + const headersMap = this[kOutHeaders]; + if (headersMap === null) return []; + + const values = ObjectValues(headersMap); + const headers = Array(values.length); + // Retain for(;;) loop for performance reasons + // Refs: https://github.com/nodejs/node/pull/30958 + for (let i = 0, l = values.length; i < l; i++) { + headers[i] = values[i][0]; + } + + return headers; +}; + + // Returns a shallow copy of the current outgoing headers. OutgoingMessage.prototype.getHeaders = function getHeaders() { const headers = this[kOutHeaders]; diff --git a/test/parallel/test-http-mutable-headers.js b/test/parallel/test-http-mutable-headers.js index c9f63acf4433f4..755a4dd66159e8 100644 --- a/test/parallel/test-http-mutable-headers.js +++ b/test/parallel/test-http-mutable-headers.js @@ -108,6 +108,10 @@ const s = http.createServer(common.mustCall((req, res) => { ['x-test-header', 'x-test-header2', 'set-cookie', 'x-test-array-header']); + assert.deepStrictEqual(res.getRawHeaderNames(), + ['x-test-header', 'X-TEST-HEADER2', + 'set-cookie', 'x-test-array-header']); + assert.strictEqual(res.hasHeader('x-test-header2'), true); assert.strictEqual(res.hasHeader('X-TEST-HEADER2'), true); assert.strictEqual(res.hasHeader('X-Test-Header2'), true); @@ -171,7 +175,10 @@ function nextTest() { let bufferedResponse = ''; - http.get({ port: s.address().port }, common.mustCall((response) => { + const req = http.get({ + port: s.address().port, + headers: { 'X-foo': 'bar' } + }, common.mustCall((response) => { switch (test) { case 'headers': assert.strictEqual(response.statusCode, 201); @@ -214,4 +221,10 @@ function nextTest() { common.mustCall(nextTest)(); })); })); + + assert.deepStrictEqual(req.getHeaderNames(), + ['x-foo', 'host']); + + assert.deepStrictEqual(req.getRawHeaderNames(), + ['X-foo', 'Host']); }