UNPKG

8.52 kBMarkdownView Raw
1# SPDY Server for node.js
2
3[![Build Status](https://travis-ci.org/spdy-http2/node-spdy.svg?branch=master)](http://travis-ci.org/spdy-http2/node-spdy)
4[![NPM version](https://badge.fury.io/js/spdy.svg)](http://badge.fury.io/js/spdy)
5[![dependencies Status](https://david-dm.org/spdy-http2/node-spdy/status.svg?style=flat-square)](https://david-dm.org/spdy-http2/node-spdy)
6[![Standard - JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](http://standardjs.com/)
7[![Waffle](https://img.shields.io/badge/track-waffle-blue.svg?style=flat-square)](https://waffle.io/spdy-http2/node-spdy)
8
9With this module you can create [HTTP2][0] / [SPDY][1] servers
10in node.js with natural http module interface and fallback to regular https
11(for browsers that don't support neither HTTP2, nor SPDY yet).
12
13This module named `spdy` but it [provides](https://github.com/indutny/node-spdy/issues/269#issuecomment-239014184) support for both http/2 (h2) and spdy (2,3,3.1). Also, `spdy` is compatible with Express.
14
15## Usage
16
17### Examples
18
19Server:
20```javascript
21var spdy = require('spdy'),
22 fs = require('fs');
23
24var options = {
25 // Private key
26 key: fs.readFileSync(__dirname + '/keys/spdy-key.pem'),
27
28 // Fullchain file or cert file (prefer the former)
29 cert: fs.readFileSync(__dirname + '/keys/spdy-fullchain.pem'),
30
31 // **optional** SPDY-specific options
32 spdy: {
33 protocols: [ 'h2', 'spdy/3.1', ..., 'http/1.1' ],
34 plain: false,
35
36 // **optional**
37 // Parse first incoming X_FORWARDED_FOR frame and put it to the
38 // headers of every request.
39 // NOTE: Use with care! This should not be used without some proxy that
40 // will *always* send X_FORWARDED_FOR
41 'x-forwarded-for': true,
42
43 connection: {
44 windowSize: 1024 * 1024, // Server's window size
45
46 // **optional** if true - server will send 3.1 frames on 3.0 *plain* spdy
47 autoSpdy31: false
48 }
49 }
50};
51
52var server = spdy.createServer(options, function(req, res) {
53 res.writeHead(200);
54 res.end('hello world!');
55});
56
57server.listen(3000);
58```
59
60Client:
61```javascript
62var spdy = require('spdy');
63var https = require('https');
64
65var agent = spdy.createAgent({
66 host: 'www.google.com',
67 port: 443,
68
69 // Optional SPDY options
70 spdy: {
71 plain: false,
72 ssl: true,
73
74 // **optional** send X_FORWARDED_FOR
75 'x-forwarded-for': '127.0.0.1'
76 }
77});
78
79https.get({
80 host: 'www.google.com',
81 agent: agent
82}, function(response) {
83 console.log('yikes');
84 // Here it goes like with any other node.js HTTP request
85 // ...
86 // And once we're done - we may close TCP connection to server
87 // NOTE: All non-closed requests will die!
88 agent.close();
89}).end();
90```
91
92Please note that if you use a custom agent, by default all connection-level
93errors will result in an uncaught exception. To handle these errors subscribe
94to the `error` event and re-emit the captured error:
95
96```javascript
97var agent = spdy.createAgent({
98 host: 'www.google.com',
99 port: 443
100}).once('error', function (err) {
101 this.emit(err);
102});
103```
104
105#### Push streams
106
107It is possible to initiate [PUSH_PROMISE][5] to send content to clients _before_
108the client requests it.
109
110```javascript
111spdy.createServer(options, function(req, res) {
112 var stream = res.push('/main.js', {
113 status: 200, // optional
114 method: 'GET', // optional
115 request: {
116 accept: '*/*'
117 },
118 response: {
119 'content-type': 'application/javascript'
120 }
121 });
122 stream.on('error', function() {
123 });
124 stream.end('alert("hello from push stream!");');
125
126 res.end('<script src="/main.js"></script>');
127}).listen(3000);
128```
129
130[PUSH_PROMISE][5] may be sent using the `push()` method on the current response
131object. The signature of the `push()` method is:
132
133`.push('/some/relative/url', { request: {...}, response: {...} }, callback)`
134
135Second argument contains headers for both PUSH_PROMISE and emulated response.
136`callback` will receive two arguments: `err` (if any error is happened) and a
137[Duplex][4] stream as the second argument.
138
139Client usage:
140```javascript
141var agent = spdy.createAgent({ /* ... */ });
142var req = http.get({
143 host: 'www.google.com',
144 agent: agent
145}, function(response) {
146});
147req.on('push', function(stream) {
148 stream.on('error', function(err) {
149 // Handle error
150 });
151 // Read data from stream
152});
153```
154
155NOTE: You're responsible for the `stream` object once given it in `.push()`
156callback or `push` event. Hence ignoring `error` event on it will result in
157uncaught exception and crash your program.
158
159#### Trailing headers
160
161Server usage:
162```javascript
163function (req, res) {
164 // Send trailing headers to client
165 res.addTrailers({ header1: 'value1', header2: 'value2' });
166
167 // On client's trailing headers
168 req.on('trailers', function(headers) {
169 // ...
170 });
171}
172```
173
174Client usage:
175```javascript
176var req = http.request({ agent: spdyAgent, /* ... */ }).function (res) {
177 // On server's trailing headers
178 res.on('trailers', function(headers) {
179 // ...
180 });
181});
182req.write('stuff');
183req.addTrailers({ /* ... */ });
184req.end();
185```
186
187#### Options
188
189All options supported by [tls][2] work with node-spdy.
190
191Additional options may be passed via `spdy` sub-object:
192
193* `plain` - if defined, server will ignore NPN and ALPN data and choose whether
194 to use spdy or plain http by looking at first data packet.
195* `ssl` - if `false` and `options.plain` is `true`, `http.Server` will be used
196 as a `base` class for created server.
197* `maxChunk` - if set and non-falsy, limits number of bytes sent in one DATA
198 chunk. Setting it to non-zero value is recommended if you care about
199 interleaving of outgoing data from multiple different streams.
200 (defaults to 8192)
201* `protocols` - list of NPN/ALPN protocols to use (default is:
202 `['h2','spdy/3.1', 'spdy/3', 'spdy/2','http/1.1', 'http/1.0']`)
203* `protocol` - use specific protocol if no NPN/ALPN ex In addition,
204* `maxStreams` - set "[maximum concurrent streams][3]" protocol option
205
206### API
207
208API is compatible with `http` and `https` module, but you can use another
209function as base class for SPDYServer.
210
211```javascript
212spdy.createServer(
213 [base class constructor, i.e. https.Server],
214 { /* keys and options */ }, // <- the only one required argument
215 [request listener]
216).listen([port], [host], [callback]);
217```
218
219Request listener will receive two arguments: `request` and `response`. They're
220both instances of `http`'s `IncomingMessage` and `OutgoingMessage`. But three
221custom properties are added to both of them: `isSpdy`, `spdyVersion`. `isSpdy`
222is `true` when the request was processed using HTTP2/SPDY protocols, it is
223`false` in case of HTTP/1.1 fallback. `spdyVersion` is either of: `2`, `3`,
224`3.1`, or `4` (for HTTP2).
225
226
227#### Contributors
228
229* [Fedor Indutny](https://github.com/indutny)
230* [Chris Strom](https://github.com/eee-c)
231* [François de Metz](https://github.com/francois2metz)
232* [Ilya Grigorik](https://github.com/igrigorik)
233* [Roberto Peon](https://github.com/grmocg)
234* [Tatsuhiro Tsujikawa](https://github.com/tatsuhiro-t)
235* [Jesse Cravens](https://github.com/jessecravens)
236
237#### LICENSE
238
239This software is licensed under the MIT License.
240
241Copyright Fedor Indutny, 2015.
242
243Permission is hereby granted, free of charge, to any person obtaining a
244copy of this software and associated documentation files (the
245"Software"), to deal in the Software without restriction, including
246without limitation the rights to use, copy, modify, merge, publish,
247distribute, sublicense, and/or sell copies of the Software, and to permit
248persons to whom the Software is furnished to do so, subject to the
249following conditions:
250
251The above copyright notice and this permission notice shall be included
252in all copies or substantial portions of the Software.
253
254THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
255OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
256MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
257NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
258DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
259OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
260USE OR OTHER DEALINGS IN THE SOFTWARE.
261
262[0]: https://http2.github.io/
263[1]: http://www.chromium.org/spdy
264[2]: http://nodejs.org/docs/latest/api/tls.html#tls.createServer
265[3]: https://httpwg.github.io/specs/rfc7540.html#SETTINGS_MAX_CONCURRENT_STREAMS
266[4]: https://iojs.org/api/stream.html#stream_class_stream_duplex
267[5]: https://httpwg.github.io/specs/rfc7540.html#PUSH_PROMISE