Skip to content

Commit 1a2a685

Browse files
committedJul 14, 2017
http2: additional cleanups, fixes and docs
* Follow the model of the existing http code and pass the headers in to js as an array. Building the array on the native side then converting it to an object on the js side is generally faster than building the object on the native side. This also allows us to eliminate some duplicated checks. * Fill in additional doc details * Work on timeouts PR-URL: nodejs#148 Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 04f3979 commit 1a2a685

File tree

8 files changed

+355
-266
lines changed

8 files changed

+355
-266
lines changed
 

‎doc/api/http2.md

+151-52
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ session.on('stream', (stream, headers, flags) => {
130130
});
131131
```
132132

133-
*Note*: User code will typically not listen for this event directly, and would
134-
instead register a handler for the `'stream'` event emitted by the `net.Server`
135-
or `tls.Server` instances returned by `http2.createServer()` and
133+
On the server side, user code will typically not listen for this event directly,
134+
and would instead register a handler for the `'stream'` event emitted by the
135+
`net.Server` or `tls.Server` instances returned by `http2.createServer()` and
136136
`http2.createSecureServer()`, respectively, as in the example below:
137137

138138
```js
@@ -164,7 +164,14 @@ not handled, the `'error'` event will be re-emitted on the `Http2Session`.
164164

165165
#### Event: 'timeout'
166166

167-
(TODO: fill in detail)
167+
After the `http2session.setTimeout()` method is used to set the timeout period
168+
for this `Http2Session`, the `'timeout'` event is emitted if there is no
169+
activity on the `Http2Session` after the configured number of milliseconds.
170+
171+
```js
172+
session.setTimeout(2000);
173+
session.on('timeout', () => { /** .. **/ });
174+
```
168175

169176
#### http2session.destroy()
170177

@@ -182,15 +189,15 @@ longer be used, otherwise `false`.
182189

183190
* Value: {[Settings Object][]}
184191

185-
An object describing the current local settings of this `Http2Session`. The
186-
local settings are local to *this* `Http2Session` instance.
192+
A prototype-less object describing the current local settings of this
193+
`Http2Session`. The local settings are local to *this* `Http2Session` instance.
187194

188195
#### http2session.remoteSettings
189196

190197
* Value: {[Settings Object][]}
191198

192-
An object describing the current remote settings of this `Http2Session`. The
193-
remote settings are set by the *connected* HTTP/2 peer.
199+
A prototype-less object describing the current remote settings of this
200+
`Http2Session`. The remote settings are set by the *connected* HTTP/2 peer.
194201

195202
#### http2session.request(headers[, options])
196203

@@ -216,41 +223,77 @@ HTTP/2 request to the connected server.
216223
This method is only available if `http2session.type` is equal to
217224
`http2.constants.NGHTTP2_SESSION_CLIENT`.
218225

219-
(TODO: fill in detail)
226+
```js
227+
const http2 = require('http2');
228+
const clientSession = http2.connect('https://localhost:1234');
229+
const {
230+
HTTP2_HEADER_PATH,
231+
HTTP2_HEADER_STATUS
232+
} = http2.constants;
233+
234+
const req = clientSession.request({ [HTTP2_HEADER_PATH]: '/' });
235+
req.on('response', (headers) => {
236+
console.log(HTTP2_HEADER_STATUS);
237+
req.on('data', (chunk) => { /** .. **/ });
238+
req.on('end', () => { /** .. **/ });
239+
});
240+
```
220241

221242
#### http2session.rstStream(stream, code)
222243

223244
* stream {Http2Stream}
224-
* code {number}
245+
* code {number} Unsigned 32-bit integer identifying the error code. Defaults to
246+
`http2.constant.NGHTTP2_NO_ERROR` (`0x00`)
225247

226248
Sends an `RST_STREAM` frame to the connected HTTP/2 peer, causing the given
227-
`Http2Stream` to be closed on both sides using error code `code`.
249+
`Http2Stream` to be closed on both sides using [error code][] `code`.
228250

229251
#### http2session.setTimeout(msecs, callback)
230252

231253
* `msecs` {number}
232254
* `callback` {Function}
233255

234-
(TODO: fill in detail)
256+
Used to set a callback function that is called when there is no activity on
257+
the `Http2Session` after `msecs` milliseconds. The given `callback` is
258+
registered as a listener on the `'timeout'` event.
235259

236260
#### http2session.shutdown(options[, callback])
237261

238262
* `options` {Object}
239263
* `graceful` {boolean} `true` to attempt a polite shutdown of the
240264
`Http2Session`.
241-
* `errorCode` {number} The HTTP/2 Error Code to return. Note that this is
242-
*not* the same thing as an HTTP Response Status Code.
265+
* `errorCode` {number} The HTTP/2 [error code][] to return. Note that this is
266+
*not* the same thing as an HTTP Response Status Code. Defaults to `0x00`
267+
(No Error).
243268
* `lastStreamID` {number} The Stream ID of the last successfully processed
244269
`Http2Stream` on this `Http2Session`.
245270
* `opaqueData` {Buffer} A `Buffer` instance containing arbitrary additional
246271
data to send to the peer upon disconnection. This is used, typically, to
247272
provide additional data for debugging failures, if necessary.
248-
* `callback` {Function}
273+
* `callback` {Function} A callback that is invoked after the session shutdown
274+
has been completed.
249275

250276
Attempts to shutdown this `Http2Session` using HTTP/2 defined procedures.
251277
If specified, the given `callback` function will be invoked once the shutdown
252278
process has completed.
253279

280+
Note that calling `http2session.shutdown()` does *not* destroy the session or
281+
tear down the `Socket` connection. It merely prompts both sessions to begin
282+
preparing to cease activity.
283+
284+
During a "graceful" shutdown, the session will first send a `GOAWAY` frame to
285+
the connected peer identifying the last processed stream as 2<sup>32</sup>-1.
286+
Then, on the next tick of the event loop, a second `GOAWAY` frame identifying
287+
the most recently processed stream identifier is sent. This process allows the
288+
remote peer to begin preparing for the connection to be terminated.
289+
290+
```js
291+
session.shutdown({
292+
graceful: true,
293+
opaqueData: Buffer.from('add some debugging data here')
294+
}, () => session.destroy());
295+
```
296+
254297
#### http2session.socket
255298

256299
* Value: {net.Socket|tls.TLSSocket}
@@ -417,7 +460,9 @@ this event is emitted, the `Http2Stream` instance is no longer usable.
417460

418461
#### Event: 'timeout'
419462

420-
(TODO: fill in detail)
463+
The `'timeout'` event is emitted after no activity is received for this
464+
`'Http2Stream'` within the number of millseconds set using
465+
`http2stream.setTimeout()`.
421466

422467
#### Event: 'trailers'
423468

@@ -427,7 +472,7 @@ trailing header fields is received. The listener callback is passed the
427472

428473
```js
429474
stream.on('trailers', (headers, flags) => {
430-
// TODO(jasnell): Fill in example
475+
console.log(headers);
431476
});
432477
```
433478

@@ -459,36 +504,38 @@ peer.
459504

460505
* Value: {number}
461506

462-
Set to the `RST_STREAM` error code when the `Http2Stream` is destroyed after
463-
either receiving an `RST_STREAM` frame from the connected peer, calling
464-
`http2stream.rstStream()`, or `http2stream.destroy()`.
507+
Set to the `RST_STREAM` [error code][] reported when the `Http2Stream` is
508+
destroyed after either receiving an `RST_STREAM` frame from the connected peer,
509+
calling `http2stream.rstStream()`, or `http2stream.destroy()`. Will be
510+
`undefined` if the `Http2Stream` has not been closed.
465511

466512
#### http2stream.rstStream(code)
467513

468-
* `code` {number}
514+
* code {number} Unsigned 32-bit integer identifying the error code. Defaults to
515+
`http2.constant.NGHTTP2_NO_ERROR` (`0x00`)
469516

470517
Sends an `RST_STREAM` frame to the connected HTTP/2 peer, causing this
471-
`Http2Stream` to be closed on both sides using error code `code`.
518+
`Http2Stream` to be closed on both sides using [error code][] `code`.
472519

473520
#### http2stream.rstWithNoError()
474521

475-
Shortcut for `http2stream.rstStream()` using error code `NO_ERROR`.
522+
Shortcut for `http2stream.rstStream()` using error code `0x00` (No Error).
476523

477524
#### http2stream.rstWithProtocolError() {
478525

479-
Shortcut for `http2stream.rstStream()` using error code `PROTOCOL_ERROR`.
526+
Shortcut for `http2stream.rstStream()` using error code `0x01` (Protocol Error).
480527

481528
#### http2stream.rstWithCancel() {
482529

483-
Shortcut for `http2stream.rstStream()` using error code `CANCEL`.
530+
Shortcut for `http2stream.rstStream()` using error code `0x08` (Cancel).
484531

485532
#### http2stream.rstWithRefuse() {
486533

487-
Shortcut for `http2stream.rstStream()` using error code `REFUSED_STREAM`.
534+
Shortcut for `http2stream.rstStream()` using error code `0x07` (Refused Stream).
488535

489536
#### http2stream.rstWithInternalError() {
490537

491-
Shortcut for `http2stream.rstStream()` using error code `INTERNAL_ERROR`.
538+
Shortcut for `http2stream.rstStream()` using error code `0x02` (Internal Error).
492539

493540
#### http2stream.session
494541

@@ -502,7 +549,15 @@ value will be `undefined` after the `Http2Stream` instance is destroyed.
502549
* `msecs` {number}
503550
* `callback` {Function}
504551

505-
(TODO: fill in detail)
552+
```js
553+
const http2 = require('http2');
554+
const client = http2.connect('http://example.org:8000');
555+
556+
const req = client.request({':path': '/'});
557+
558+
// Cancel the stream if there's no activity after 5 seconds
559+
req.setTimeout(5000, () => req.rstStreamWithCancel());
560+
```
506561

507562
#### http2stream.state
508563

@@ -534,7 +589,7 @@ the headers.
534589

535590
```js
536591
stream.on('headers', (headers, flags) => {
537-
// TODO(jasnell): Fill in example
592+
console.log(headers);
538593
});
539594
```
540595

@@ -546,7 +601,7 @@ associated with the headers.
546601

547602
```js
548603
stream.on('push', (headers, flags) => {
549-
// TODO(jasnell): Fill in example
604+
console.log(headers);
550605
});
551606
```
552607

@@ -577,18 +632,6 @@ used exclusively on HTTP/2 Servers. `Http2Stream` instances on the server
577632
provide additional methods such as `http2stream.pushStream()` and
578633
`http2stream.respond()` that are only relevant on the server.
579634

580-
#### Event: 'request'
581-
582-
The `'request'` event is emitted when a block of headers associated with an
583-
HTTP request is received. The listener callback is passed the [Headers Object][]
584-
and flags associated with the headers.
585-
586-
```js
587-
stream.on('request', (headers, flags) => {
588-
// TODO(jasnell): Fill in example
589-
});
590-
```
591-
592635
#### http2stream.additionalHeaders(headers)
593636

594637
* `headers` {[Headers Object][]}
@@ -608,18 +651,38 @@ Sends an additional informational `HEADERS` frame to the connected HTTP/2 peer.
608651
* `weight` {number} Specifies the relative dependency of a stream in relation
609652
to other streams with the same `parent`. The value is a number between `1`
610653
and `256` (inclusive).
611-
* `callback` {Function}
654+
* `callback` {Function} Callback that is called once the push stream has been
655+
initiated.
656+
657+
Initiates a push stream. The callback is invoked with the new `Htt2Stream`
658+
instance created for the push stream.
612659

613-
Initiates a push stream.
614-
(TODO: fill in detail)
660+
```js
661+
const http2 = require('http2');
662+
const server = http2.createServer();
663+
server.on('stream', (stream) => {
664+
stream.respond({':status': 200});
665+
stream.pushStream({':path': '/'}, (pushStream) => {
666+
pushStream.respond({':status': 200});
667+
pushStream.end('some pushed data');
668+
});
669+
stream.end('some data');
670+
});
671+
```
615672

616673
#### http2stream.respond([headers[, options]])
617674

618675
* `headers` {[Headers Object][]}
619676
* `options` {Object}
620677

621-
Initiates a response.
622-
(TODO: fill in detail)
678+
```js
679+
const http2 = require('http2');
680+
const server = http2.createServer();
681+
server.on('stream', (stream) => {
682+
stream.respond({':status': 200});
683+
stream.end('some data');
684+
});
685+
```
623686

624687
### Class: Http2Server
625688

@@ -667,7 +730,8 @@ server.on('stream', (stream, headers, flags) => {
667730

668731
#### Event: 'timeout'
669732

670-
(TODO: fill in detail)
733+
The `'timeout'` event is emitted when there is no activity on the Server for
734+
a given number of milliseconds set using `http2server.setTimeout()`.
671735

672736
### Class: Http2SecureServer
673737

@@ -717,7 +781,8 @@ server.on('stream', (stream, headers, flags) => {
717781

718782
#### Event: 'timeout'
719783

720-
(TODO: fill in detail)
784+
The `'timeout'` event is emitted when there is no activity on the Server for
785+
a given number of milliseconds set using `http2server.setTimeout()`.
721786

722787
### http2.getDefaultSettings()
723788

@@ -882,11 +947,37 @@ server.listen(80);
882947
* Returns `Http2Session`
883948

884949
Returns a HTTP/2 client `Http2Session` instance.
885-
(TODO: fill in detail)
950+
951+
```js
952+
const http2 = require('http2');
953+
const client = http2.connect('https://localhost:1234');
954+
955+
/** use the client **/
956+
957+
client.destroy();
958+
```
886959

887960
### http2.constants
888961

889-
(TODO: Fill in details)
962+
#### Error Codes for RST_STREAM and GOAWAY
963+
<a id="error_codes"></a>
964+
965+
| Value | Name | Constant |
966+
|-------|---------------------|-----------------------------------------------|
967+
| 0x00 | No Error | `http2.constants.NGHTTP2_NO_ERROR` |
968+
| 0x01 | Protocol Error | `http2.constants.NGHTTP2_PROTOCOL_ERROR` |
969+
| 0x02 | Internal Error | `http2.constants.NGHTTP2_INTERNAL_ERROR` |
970+
| 0x03 | Flow Control Error | `http2.constants.NGHTTP2_FLOW_CONTROL_ERROR` |
971+
| 0x04 | Settings Timeout | `http2.constants.NGHTTP2_SETTINGS_TIMEOUT` |
972+
| 0x05 | Stream Closed | `http2.constants.NGHTTP2_STREAM_CLOSED` |
973+
| 0x06 | Frame Size Error | `http2.constants.NGHTTP2_FRAME_SIZE_ERROR` |
974+
| 0x07 | Refused Stream | `http2.constants.NGHTTP2_REFUSED_STREAM` |
975+
| 0x08 | Cancel | `http2.constants.NGHTTP2_CANCEL` |
976+
| 0x09 | Compression Error | `http2.constants.NGHTTP2_COMPRESSION_ERROR` |
977+
| 0x0a | Connect Error | `http2.constants.NGHTTP2_CONNECT_ERROR` |
978+
| 0x0b | Enhance Your Calm | `http2.constants.NGHTTP2_ENHANCE_YOUR_CALM` |
979+
| 0x0c | Inadequate Security | `http2.constants.NGHTTP2_INADEQUATE_SECURITY` |
980+
| 0x0d | HTTP/1.1 Required | `http2.constants.NGHTTP2_HTTP_1_1_REQUIRED` |
890981

891982
### Headers Object
892983

@@ -912,7 +1003,14 @@ prototype. This means that normal JavaScript object methods such as
9121003
`Object.prototype.toString()` and `Object.prototype.hasOwnProperty()` will
9131004
not work.
9141005

915-
(TODO: Fill in more detail)
1006+
```js
1007+
const http2 = require('http2');
1008+
const server = http2.createServer();
1009+
server.on('stream', (stream, headers) => {
1010+
console.log(headers[':path']);
1011+
console.log(headers.ABC);
1012+
});
1013+
```
9161014

9171015
### Settings Object
9181016

@@ -1012,3 +1110,4 @@ TBD
10121110
[ServerHttp2Stream]: #http2_class_serverhttp2stream
10131111
[Settings Object]: #http2_settings_object
10141112
[Using options.selectPadding]: #http2_using_options_selectpadding
1113+
[error code]: #error_codes

0 commit comments

Comments
 (0)
Please sign in to comment.