-
-
Notifications
You must be signed in to change notification settings - Fork 33.7k
http2: allow Host in HTTP/2 requests #34664
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,10 @@ | |||||||||||||
| <!-- YAML | ||||||||||||||
| added: v8.4.0 | ||||||||||||||
| changes: | ||||||||||||||
| - version: REPLACEME | ||||||||||||||
| pr-url: https://github.com/nodejs/node/pull/34664 | ||||||||||||||
| description: Requests with the `host` header (with or without | ||||||||||||||
| `:authority`) can now be sent / received. | ||||||||||||||
| - version: v10.10.0 | ||||||||||||||
| pr-url: https://github.com/nodejs/node/pull/22466 | ||||||||||||||
| description: HTTP/2 is now Stable. Previously, it had been Experimental. | ||||||||||||||
|
|
@@ -2530,7 +2534,7 @@ For incoming headers: | |||||||||||||
| `access-control-max-age`, `access-control-request-method`, `content-encoding`, | ||||||||||||||
| `content-language`, `content-length`, `content-location`, `content-md5`, | ||||||||||||||
| `content-range`, `content-type`, `date`, `dnt`, `etag`, `expires`, `from`, | ||||||||||||||
| `if-match`, `if-modified-since`, `if-none-match`, `if-range`, | ||||||||||||||
| `host`, `if-match`, `if-modified-since`, `if-none-match`, `if-range`, | ||||||||||||||
| `if-unmodified-since`, `last-modified`, `location`, `max-forwards`, | ||||||||||||||
| `proxy-authorization`, `range`, `referer`,`retry-after`, `tk`, | ||||||||||||||
| `upgrade-insecure-requests`, `user-agent` or `x-content-type-options` are | ||||||||||||||
|
|
@@ -2908,8 +2912,9 @@ added: v8.4.0 | |||||||||||||
|
|
||||||||||||||
| * {string} | ||||||||||||||
|
|
||||||||||||||
| The request authority pseudo header field. It can also be accessed via | ||||||||||||||
| `req.headers[':authority']`. | ||||||||||||||
| The request authority pseudo header field. Because HTTP/2 allows requests | ||||||||||||||
| to set either `:authority` or `host`, this value is derived from | ||||||||||||||
| `req.headers[':authority']` if present, `req.headers['host']` otherwise. | ||||||||||||||
mildsunrise marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||
|
|
||||||||||||||
| #### `request.complete` | ||||||||||||||
| <!-- YAML | ||||||||||||||
|
|
@@ -3708,6 +3713,25 @@ following additional properties: | |||||||||||||
| * `type` {string} Either `'server'` or `'client'` to identify the type of | ||||||||||||||
| `Http2Session`. | ||||||||||||||
|
|
||||||||||||||
| ## Note on `:authority` and `host` | ||||||||||||||
|
|
||||||||||||||
| HTTP/2 requires requests to have either the `:authority` pseudo-header | ||||||||||||||
| or the `host` header. Using `:authority` should be preferred when | ||||||||||||||
| constructing an HTTP/2 request directly, and `host` should be | ||||||||||||||
| preferred when converting from HTTP/1 (in proxies, for instance). | ||||||||||||||
|
||||||||||||||
| or the `host` header. Using `:authority` should be preferred when | |
| constructing an HTTP/2 request directly, and `host` should be | |
| preferred when converting from HTTP/1 (in proxies, for instance). | |
| or the `host` header. Use `:authority` when | |
| constructing an HTTP/2 request directly, and `host` | |
| when converting from HTTP/1 (in proxies, for instance). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the pointers 💙 I'm not sure on this one, though... the spec only says it's a "preferred form", not imperative or anything, and I'm not sure how often this preference is honored in practice... (we didn't even allow that form to begin with)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'll apply the suggestion with Prefer instead of Use
mildsunrise marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
mildsunrise marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| 'use strict'; | ||
|
|
||
| const common = require('../common'); | ||
| if (!common.hasCrypto) | ||
| common.skip('missing crypto'); | ||
| const assert = require('assert'); | ||
| const h2 = require('http2'); | ||
|
|
||
| // Requests using host instead of :authority should be allowed | ||
| // and Http2ServerRequest.authority should fall back to host | ||
|
|
||
| // :authority should NOT be auto-filled if host is present | ||
|
|
||
| const server = h2.createServer(); | ||
| server.listen(0, common.mustCall(function() { | ||
| const port = server.address().port; | ||
| server.once('request', common.mustCall(function(request, response) { | ||
| const expected = { | ||
| ':path': '/foobar', | ||
| ':method': 'GET', | ||
| ':scheme': 'http', | ||
| 'host': `localhost:${port}` | ||
| }; | ||
|
|
||
| assert.strictEqual(request.authority, expected.host); | ||
|
|
||
| const headers = request.headers; | ||
| for (const [name, value] of Object.entries(expected)) { | ||
| assert.strictEqual(headers[name], value); | ||
| } | ||
|
|
||
| const rawHeaders = request.rawHeaders; | ||
| for (const [name, value] of Object.entries(expected)) { | ||
| const position = rawHeaders.indexOf(name); | ||
| assert.notStrictEqual(position, -1); | ||
| assert.strictEqual(rawHeaders[position + 1], value); | ||
| } | ||
|
|
||
| assert(!Object.hasOwnProperty.call(headers, ':authority')); | ||
| assert(!Object.hasOwnProperty.call(rawHeaders, ':authority')); | ||
|
|
||
| response.on('finish', common.mustCall(function() { | ||
| server.close(); | ||
| })); | ||
| response.end(); | ||
| })); | ||
|
|
||
| const url = `http://localhost:${port}`; | ||
| const client = h2.connect(url, common.mustCall(function() { | ||
| const headers = { | ||
| ':path': '/foobar', | ||
| ':method': 'GET', | ||
| ':scheme': 'http', | ||
| 'host': `localhost:${port}` | ||
| }; | ||
| const request = client.request(headers); | ||
| request.on('end', common.mustCall(function() { | ||
| client.close(); | ||
| })); | ||
| request.end(); | ||
| request.resume(); | ||
| })); | ||
| })); |
Uh oh!
There was an error while loading. Please reload this page.