Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions doc/api/http2.md
Original file line number Diff line number Diff line change
Expand Up @@ -4189,6 +4189,53 @@ removeAllHeaders(request.headers);
assert(request.url); // Fails because the :path header has been removed
```

#### `request.headersDistinct`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docs here are duplicated. One of these needs removing.


<!-- YAML
added:
- v18.3.0
- v16.17.0

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In whichever doc you keep, the version number here should be left as a placeholder. It'll be automatically filled out when this is released, like so:

added:
  - version: REPLACEME

-->

* Type: {Object}

Similar to [`request.headers`][], but there is no join logic and the values are

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link name is defined in http.md but not here in http2.md.

If you want to keep it in the de-dupe, we'll need another definition here to make the link work. You can see those at the bottom of the file, just add this in there alphabetically.

always arrays of strings, even for headers received just once.

The object has a null prototype and should not be accessed using the `in`
operator.

```js
// Prints something like:
//
// { 'user-agent': ['curl/7.22.0'],
// host: ['127.0.0.1:8000'],
// accept: ['*/*'] }
console.log(request.headersDistinct);
```

<!-- YAML
added: v8.4.0
-->

* Type: {Object}

Similar to `request.headers`, but preserves duplicate header values.
Each property is an array containing all values received for that header.

The object has a null prototype and should not be accessed using the `in`
operator.

```js
// Prints something like:
//
// {
// host: ['127.0.0.1:8000'],
// accept: ['text/html', 'application/json']
// }
console.log(request.headersDistinct);
```

#### `request.httpVersion`

<!-- YAML
Expand Down
25 changes: 25 additions & 0 deletions lib/internal/http2/compat.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ const kRawTrailers = Symbol('rawTrailers');
const kSetHeader = Symbol('setHeader');
const kAppendHeader = Symbol('appendHeader');
const kAborted = Symbol('aborted');
const kHeadersDistinct = Symbol('headersDistinct');

let statusMessageWarned = false;
let statusConnectionHeaderWarned = false;
Expand Down Expand Up @@ -323,6 +324,7 @@ class Http2ServerRequest extends Readable {
this[kRawTrailers] = [];
this[kStream] = stream;
this[kAborted] = false;
this[kHeadersDistinct] = undefined;
stream[kProxySocket] = null;
stream[kRequest] = this;

Expand Down Expand Up @@ -356,6 +358,29 @@ class Http2ServerRequest extends Readable {
return this[kHeaders];
}

get headersDistinct() {
if (this[kHeadersDistinct] === undefined) {
const distinct = { __proto__: null };

const raw = this[kRawHeaders];

for (let i = 0; i < raw.length; i += 2) {
const name = raw[i].toLowerCase();
const value = raw[i + 1];

if (distinct[name] === undefined) {
distinct[name] = [value];
} else {
distinct[name].push(value);
}
}

this[kHeadersDistinct] = distinct;
}

return this[kHeadersDistinct];
}

get rawHeaders() {
return this[kRawHeaders];
}
Expand Down
19 changes: 19 additions & 0 deletions test/parallel/test-http2-compat-serverrequest-headers.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,25 @@
assert.strictEqual(rawHeaders[position + 1], value);
}

const headersDistinct = request.headersDistinct;

assert.deepStrictEqual(
headersDistinct,
{
__proto__: null,

Check failure on line 47 in test/parallel/test-http2-compat-serverrequest-headers.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Inconsistently quoted property '__proto__' found
':path': ['/foobar'],
':method': ['GET'],
':scheme': ['http'],
':authority': [`localhost:${port}`],
'foo-bar': ['abc123'],
}
);

assert.strictEqual(
headersDistinct,
request.headersDistinct
);

Check failure on line 60 in test/parallel/test-http2-compat-serverrequest-headers.js

View workflow job for this annotation

GitHub Actions / lint-js-and-md

Trailing spaces not allowed
request.url = '/one';
assert.strictEqual(request.url, '/one');

Expand Down
Loading