From 8b8c2a9685a999adb0948663805edea410572fc1 Mon Sep 17 00:00:00 2001 From: James M Snell Date: Sun, 16 Sep 2018 19:13:11 -0700 Subject: [PATCH 1/5] http2: add origin frame support --- doc/api/errors.md | 10 ++ doc/api/http2.md | 77 +++++++++++++ lib/internal/errors.js | 4 + lib/internal/http2/core.js | 103 ++++++++++++++--- src/env.h | 1 + src/node_http2.cc | 126 +++++++++++++++++++- src/node_http2.h | 27 ++++- test/parallel/test-http2-origin.js | 179 +++++++++++++++++++++++++++++ 8 files changed, 503 insertions(+), 24 deletions(-) create mode 100644 test/parallel/test-http2-origin.js diff --git a/doc/api/errors.md b/doc/api/errors.md index 7e77d84ed08665..42ead73967e297 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -920,6 +920,11 @@ An invalid HTTP/2 header value was specified. An invalid HTTP informational status code has been specified. Informational status codes must be an integer between `100` and `199` (inclusive). + +### ERR_HTTP2_INVALID_ORIGIN + +HTTP/2 ORIGIN frames require a valid origin. + ### ERR_HTTP2_INVALID_PACKED_SETTINGS_LENGTH @@ -970,6 +975,11 @@ Nested push streams are not permitted. An attempt was made to directly manipulate (read, write, pause, resume, etc.) a socket attached to an `Http2Session`. + +### ERR_HTTP2_ORIGIN_LENGTH + +HTTP/2 ORIGIN frames are limited to a length of 16382 bytes. + ### ERR_HTTP2_OUT_OF_STREAMS diff --git a/doc/api/http2.md b/doc/api/http2.md index feeb66aa88c108..316d76627b1e7e 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -432,6 +432,8 @@ If the `Http2Session` is connected to a `TLSSocket`, the `originSet` property will return an `Array` of origins for which the `Http2Session` may be considered authoritative. +The `originSet` property is only available when using a secure TLS connection. + #### http2session.pendingSettingsAck + +* `origins` { string } One or more URL Strings passed as separate arguments. + +Submits an `ORIGIN` frame (as defined by [RFC 8336][]) to the connected client. + +```js +const http2 = require('http2'); +const options = getSecureOptionsSomehow(); +const server = http2.createSecureServer(options); +server.on('stream', (stream) => { + stream.respond(); + stream.end('ok'); +}); +server.on('session', (session) => { + session.origin('https://example.com', 'https://example.org'); +}); +``` + +When a string is passed as an `origin`, it will be parsed as a URL and the +origin will be derived. For instance, the origin for the HTTP URL +`'https://example.org/foo/bar'` is the ASCII string +`'https://example.org'`. An error will be thrown if either the given string +cannot be parsed as a URL or if a valid origin cannot be derived. + +A `URL` object, or any object with an `origin` property, may be passed as +an `origin`, in which case the value of the `origin` property will be +used. The value of the `origin` property *must* be a properly serialized +ASCII origin. + +Alternatively, the `origins` option may be used when creating a new HTTP/2 +server using either the `http2.createServer()` or `http2.createSecureServer()` +methods: + +```js +const http2 = require('http2'); +const options = getSecureOptionsSomehow(); +options.origins = ['http://example.com', 'http://example.org']; +const server = http2.createSecureServer(options); +server.on('stream', (stream) => { + stream.respond(); + stream.end('ok'); +}); +``` + ### Class: ClientHttp2Session + +* `origins` {string[]} + +The `'origin'` event is emitted whenever an `ORIGIN` frame is received by +the client. The event is emitted with an array of `origin` strings. The +`http2session.originSet` will be updated to include the received +origins. + +```js +const http2 = require('http2'); +const client = http2.connect('https://example.org'); + +client.on('origin', (origins) => { + for (let n = 0; n < origins.length; n++) + console.log(origins[n]); +}); +``` + +The `'origin'` event is only emitted when using a secure TLS connection. + #### clienthttp2session.request(headers[, options]) -* `origins` { string } One or more URL Strings passed as separate arguments. +* `origins` { string | URL | Object } One or more URL Strings passed as + separate arguments. Submits an `ORIGIN` frame (as defined by [RFC 8336][]) to the connected client to advertise the set of origins for which the server is capable of providing @@ -708,13 +709,12 @@ used. The value of the `origin` property *must* be a properly serialized ASCII origin. Alternatively, the `origins` option may be used when creating a new HTTP/2 -server using either the `http2.createServer()` or `http2.createSecureServer()` -methods: +server using the `http2.createSecureServer()` method: ```js const http2 = require('http2'); const options = getSecureOptionsSomehow(); -options.origins = ['http://example.com', 'http://example.org']; +options.origins = ['http://example.com', 'https://example.org']; const server = http2.createSecureServer(options); server.on('stream', (stream) => { stream.respond(); @@ -1990,6 +1990,10 @@ server.listen(80);