source: trip-planner-front/node_modules/sockjs/README.md@ 571e0df

Last change on this file since 571e0df was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 16.3 KB
Line 
1[![NPM version](https://badge.fury.io/js/sockjs.svg)](http://badge.fury.io/js/sockjs)
2
3SockJS family:
4
5 * [SockJS-client](https://github.com/sockjs/sockjs-client) JavaScript client library
6 * [SockJS-node](https://github.com/sockjs/sockjs-node) Node.js server
7 * [SockJS-erlang](https://github.com/sockjs/sockjs-erlang) Erlang server
8 * [SockJS-tornado](https://github.com/MrJoes/sockjs-tornado) Python/Tornado server
9 * [vert.x](https://github.com/eclipse/vert.x) Java/vert.x server
10
11Work in progress:
12
13 * [SockJS-ruby](https://github.com/nyarly/sockjs-ruby)
14 * [SockJS-netty](https://github.com/cgbystrom/sockjs-netty)
15 * [SockJS-gevent](https://github.com/sdiehl/sockjs-gevent) ([and a fork](https://github.com/njoyce/sockjs-gevent))
16 * [pyramid-SockJS](https://github.com/fafhrd91/pyramid_sockjs)
17 * [wildcloud-websockets](https://github.com/wildcloud/wildcloud-websockets)
18 * [SockJS-cyclone](https://github.com/flaviogrossi/sockjs-cyclone)
19 * [SockJS-twisted](https://github.com/Fugiman/sockjs-twisted/)
20 * [wai-SockJS](https://github.com/Palmik/wai-sockjs)
21 * [SockJS-perl](https://github.com/vti/sockjs-perl)
22 * [SockJS-go](https://github.com/igm/sockjs-go/)
23
24What is SockJS?
25===============
26
27SockJS is a JavaScript library (for browsers) that provides a WebSocket-like
28object. SockJS gives you a coherent, cross-browser, Javascript API
29which creates a low latency, full duplex, cross-domain communication
30channel between the browser and the web server, with WebSockets or without.
31This necessitates the use of a server, which this is one version of, for Node.js.
32
33
34SockJS-node server
35==================
36
37SockJS-node is a Node.js server side counterpart of
38[SockJS-client browser library](https://github.com/sockjs/sockjs-client)
39written in CoffeeScript.
40
41To install `sockjs-node` run:
42
43 npm install sockjs
44
45A simplified echo SockJS server could look more or less like:
46
47```javascript
48var http = require('http');
49var sockjs = require('sockjs');
50
51var echo = sockjs.createServer();
52echo.on('connection', function(conn) {
53 conn.on('data', function(message) {
54 conn.write(message);
55 });
56 conn.on('close', function() {});
57});
58
59var server = http.createServer();
60echo.installHandlers(server, {prefix:'/echo'});
61server.listen(9999, '0.0.0.0');
62```
63
64(Take look at
65[examples](https://github.com/sockjs/sockjs-node/tree/master/examples/echo)
66directory for a complete version.)
67
68Subscribe to
69[SockJS mailing list](https://groups.google.com/forum/#!forum/sockjs) for
70discussions and support.
71
72
73SockJS-node API
74---------------
75
76The API design is based on common Node APIs like the
77[Streams API](http://nodejs.org/docs/v0.5.8/api/streams.html) or the
78[Http.Server API](http://nodejs.org/docs/v0.5.8/api/http.html#http.Server).
79
80### Server class
81
82SockJS module is generating a `Server` class, similar to
83[Node.js http.createServer](http://nodejs.org/docs/v0.5.8/api/http.html#http.createServer)
84module.
85
86```javascript
87var sockjs_server = sockjs.createServer(options);
88```
89
90Where `options` is a hash which can contain:
91
92<dl>
93<dt>sockjs_url (string)</dt>
94<dd>Transports which don't support cross-domain communication natively
95 ('eventsource' to name one) use an iframe trick. A simple page is
96 served from the SockJS server (using its foreign domain) and is
97 placed in an invisible iframe. Code run from this iframe doesn't
98 need to worry about cross-domain issues, as it's being run from
99 domain local to the SockJS server. This iframe also does need to
100 load SockJS javascript client library, and this option lets you specify
101 its url (if you're unsure, point it to
102 <a href="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js">
103 the latest minified SockJS client release</a>, this is the default).
104 You must explicitly specify this url on the server side for security
105 reasons - we don't want the possibility of running any foreign
106 javascript within the SockJS domain (aka cross site scripting attack).
107 Also, sockjs javascript library is probably already cached by the
108 browser - it makes sense to reuse the sockjs url you're using in
109 normally.</dd>
110
111<dt>prefix (string regex)</dt>
112<dd>A url prefix for the server. All http requests which paths begins
113 with selected prefix will be handled by SockJS. All other requests
114 will be passed through, to previously registered handlers.</dd>
115
116<dt>response_limit (integer)</dt>
117<dd>Most streaming transports save responses on the client side and
118 don't free memory used by delivered messages. Such transports need
119 to be garbage-collected once in a while. `response_limit` sets
120 a minimum number of bytes that can be send over a single http streaming
121 request before it will be closed. After that client needs to open
122 new request. Setting this value to one effectively disables
123 streaming and will make streaming transports to behave like polling
124 transports. The default value is 128K.</dd>
125
126<dt>websocket (boolean)</dt>
127<dd>Some load balancers don't support websockets. This option can be used
128 to disable websockets support by the server. By default websockets are
129 enabled.</dd>
130
131<dt>jsessionid (boolean or function)</dt>
132<dd>Some hosting providers enable sticky sessions only to requests that
133 have JSESSIONID cookie set. This setting controls if the server should
134 set this cookie to a dummy value. By default setting JSESSIONID cookie
135 is disabled. More sophisticated behaviour can be achieved by supplying
136 a function.</dd>
137
138<dt>log (function(severity, message))</dt>
139<dd>It's quite useful, especially for debugging, to see some messages
140 printed by a SockJS-node library. This is done using this `log`
141 function, which is by default set to `console.log`. If this
142 behaviour annoys you for some reason, override `log` setting with a
143 custom handler. The following `severities` are used: `debug`
144 (miscellaneous logs), `info` (requests logs), `error` (serious
145 errors, consider filing an issue).</dd>
146
147<dt>heartbeat_delay (milliseconds)</dt>
148<dd>In order to keep proxies and load balancers from closing long
149 running http requests we need to pretend that the connection is
150 active and send a heartbeat packet once in a while. This setting
151 controls how often this is done. By default a heartbeat packet is
152 sent every 25 seconds. </dd>
153
154<dt>disconnect_delay (milliseconds)</dt>
155<dd>The server sends a `close` event when a client receiving
156 connection have not been seen for a while. This delay is configured
157 by this setting. By default the `close` event will be emitted when a
158 receiving connection wasn't seen for 5 seconds. </dd>
159
160<dt>disable_cors (boolean)</dt>
161<dd>Enabling this option will prevent
162 <a href="https://en.wikipedia.org/wiki/Cross-origin_resource_sharing">CORS</a>
163 headers from being included in the HTTP response. Can be used when the
164 sockjs client is known to be connecting from the same origin as the
165 sockjs server.</dd>
166</dl>
167
168
169### Server instance
170
171Once you have create `Server` instance you can hook it to the
172[http.Server instance](http://nodejs.org/docs/v0.5.8/api/http.html#http.createServer).
173
174```javascript
175var http_server = http.createServer();
176sockjs_server.installHandlers(http_server, options);
177http_server.listen(...);
178```
179
180Where `options` can overshadow options given when creating `Server`
181instance.
182
183`Server` instance is an
184[EventEmitter](http://nodejs.org/docs/v0.4.10/api/events.html#events.EventEmitter),
185and emits following event:
186
187<dl>
188<dt>Event: connection (connection)</dt>
189<dd>A new connection has been successfully opened.</dd>
190</dl>
191
192All http requests that don't go under the path selected by `prefix`
193will remain unanswered and will be passed to previously registered
194handlers. You must install your custom http handlers before calling
195`installHandlers`.
196
197### Connection instance
198
199A `Connection` instance supports
200[Node Stream API](http://nodejs.org/docs/v0.5.8/api/streams.html) and
201has following methods and properties:
202
203<dl>
204<dt>Property: readable (boolean)</dt>
205<dd>Is the stream readable?</dd>
206
207<dt>Property: writable (boolean)</dt>
208<dd>Is the stream writable?</dd>
209
210<dt>Property: remoteAddress (string)</dt>
211<dd>Last known IP address of the client.</dd>
212
213<dt>Property: remotePort (number)</dt>
214<dd>Last known port number of the client.</dd>
215
216<dt>Property: address (object)</dt>
217<dd>Hash with 'address' and 'port' fields.</dd>
218
219<dt>Property: headers (object)</dt>
220<dd>Hash containing various headers copied from last receiving request
221 on that connection. Exposed headers include: `origin`, `referer`
222 and `x-forwarded-for` (and friends). We explicitly do not grant
223 access to `cookie` header, as using it may easily lead to security
224 issues (for details read the section "Authorisation").</dd>
225
226<dt>Property: url (string)</dt>
227<dd><a href="http://nodejs.org/docs/v0.4.10/api/http.html#request.url">Url</a>
228 property copied from last request.</dd>
229
230<dt>Property: pathname (string)</dt>
231<dd>`pathname` from parsed url, for convenience.</dd>
232
233<dt>Property: prefix (string)</dt>
234<dd>Prefix of the url on which the request was handled.</dd>
235
236<dt>Property: protocol (string)</dt>
237<dd>Protocol used by the connection. Keep in mind that some protocols
238 are indistinguishable - for example "xhr-polling" and "xdr-polling".</dd>
239
240<dt>Property: readyState (integer)</dt>
241<dd>Current state of the connection:
242 0-connecting, 1-open, 2-closing, 3-closed.</dd>
243
244<dt>write(message)</dt>
245<dd>Sends a message over opened connection. A message must be a
246 non-empty string. It's illegal to send a message after the connection was
247 closed (either after 'close' or 'end' method or 'close' event).</dd>
248
249<dt>close([code], [reason])</dt>
250<dd>Asks the remote client to disconnect. 'code' and 'reason'
251 parameters are optional and can be used to share the reason of
252 disconnection.</dd>
253
254<dt>end()</dt>
255<dd>Asks the remote client to disconnect with default 'code' and
256 'reason' values.</dd>
257
258</dl>
259
260A `Connection` instance emits the following events:
261
262<dl>
263<dt>Event: data (message)</dt>
264<dd>A message arrived on the connection. Message is a unicode
265 string.</dd>
266
267<dt>Event: close ()</dt>
268<dd>Connection was closed. This event is triggered exactly once for
269 every connection.</dd>
270</dl>
271
272For example:
273
274```javascript
275sockjs_server.on('connection', function(conn) {
276 console.log('connection' + conn);
277 conn.on('close', function() {
278 console.log('close ' + conn);
279 });
280 conn.on('data', function(message) {
281 console.log('message ' + conn,
282 message);
283 });
284});
285```
286
287### Footnote
288
289A fully working echo server does need a bit more boilerplate (to
290handle requests unanswered by SockJS), see the
291[`echo` example](https://github.com/sockjs/sockjs-node/tree/master/examples/echo)
292for a complete code.
293
294### Examples
295
296If you want to see samples of running code, take a look at:
297
298 * [./examples/echo](https://github.com/sockjs/sockjs-node/tree/master/examples/echo)
299 directory, which contains a full example of a echo server.
300 * [./examples/test_server](https://github.com/sockjs/sockjs-node/tree/master/examples/test_server) a standard SockJS test server.
301
302
303Connecting to SockJS-node without the client
304--------------------------------------------
305
306Although the main point of SockJS it to enable browser-to-server
307connectivity, it is possible to connect to SockJS from an external
308application. Any SockJS server complying with 0.3 protocol does
309support a raw WebSocket url. The raw WebSocket url for the test server
310looks like:
311
312 * ws://localhost:8081/echo/websocket
313
314You can connect any WebSocket RFC 6455 compliant WebSocket client to
315this url. This can be a command line client, external application,
316third party code or even a browser (though I don't know why you would
317want to do so).
318
319Note: This endpoint will *not send any heartbeat packets*.
320
321
322Deployment and load balancing
323-----------------------------
324
325There are two issues that need to be considered when planning a
326non-trivial SockJS-node deployment: WebSocket-compatible load balancer
327and sticky sessions (aka session affinity).
328
329### WebSocket compatible load balancer
330
331Often WebSockets don't play nicely with proxies and load balancers.
332Deploying a SockJS server behind Nginx or Apache could be painful.
333
334Fortunately recent versions of an excellent load balancer
335[HAProxy](http://haproxy.1wt.eu/) are able to proxy WebSocket
336connections. We propose to put HAProxy as a front line load balancer
337and use it to split SockJS traffic from normal HTTP data. Take a look
338at the sample
339[SockJS HAProxy configuration](https://github.com/sockjs/sockjs-node/blob/master/examples/haproxy.cfg).
340
341The config also shows how to use HAproxy balancing to split traffic
342between multiple Node.js servers. You can also do balancing using dns
343names.
344
345### Sticky sessions
346
347If you plan deploying more than one SockJS server, you must make sure
348that all HTTP requests for a single session will hit the same server.
349SockJS has two mechanisms that can be useful to achieve that:
350
351 * Urls are prefixed with server and session id numbers, like:
352 `/resource/<server_number>/<session_id>/transport`. This is
353 useful for load balancers that support prefix-based affinity
354 (HAProxy does).
355 * `JSESSIONID` cookie is being set by SockJS-node. Many load
356 balancers turn on sticky sessions if that cookie is set. This
357 technique is derived from Java applications, where sticky sessions
358 are often necessary. HAProxy does support this method, as well as
359 some hosting providers, for example CloudFoundry. In order to
360 enable this method on the client side, please supply a
361 `cookie:true` option to SockJS constructor.
362
363
364Development and testing
365-----------------------
366
367If you want to work on SockJS-node source code, you need to clone the
368git repo and follow these steps. First you need to install
369dependencies:
370
371 cd sockjs-node
372 npm install
373 npm install --dev
374 ln -s .. node_modules/sockjs
375
376You're ready to compile CoffeeScript:
377
378 make build
379
380If compilation succeeds you may want to test if your changes pass all
381the tests. Currently, there are two separate test suites. For both of
382them you need to start a SockJS-node test server (by default listening
383on port 8081):
384
385 make test_server
386
387### SockJS-protocol Python tests
388
389To run it run something like:
390
391 cd sockjs-protocol
392 make test_deps
393 ./venv/bin/python sockjs-protocol.py
394
395For details see
396[SockJS-protocol README](https://github.com/sockjs/sockjs-protocol#readme).
397
398### SockJS-client QUnit tests
399
400You need to start a second web server (by default listening on 8080)
401that is serving various static html and javascript files:
402
403 cd sockjs-client
404 make test
405
406At that point you should have two web servers running: sockjs-node on
4078081 and sockjs-client on 8080. When you open the browser on
408[http://localhost:8080/](http://localhost:8080/) you should be able
409run the QUnit tests against your sockjs-node server.
410
411For details see
412[SockJS-client README](https://github.com/sockjs/sockjs-client#readme).
413
414Additionally, if you're doing more serious development consider using
415`make serve`, which will automatically the server when you modify the
416source code.
417
418
419Various issues and design considerations
420----------------------------------------
421
422### Authorisation
423
424SockJS-node does not expose cookies to the application. This is done
425deliberately as using cookie-based authorisation with SockJS simply
426doesn't make sense and will lead to security issues.
427
428Cookies are a contract between a browser and an http server, and are
429identified by a domain name. If a browser has a cookie set for
430particular domain, it will pass it as a part of all http requests to
431the host. But to get various transports working, SockJS uses a middleman
432- an iframe hosted from target SockJS domain. That means the server
433will receive requests from the iframe, and not from the real
434domain. The domain of an iframe is the same as the SockJS domain. The
435problem is that any website can embed the iframe and communicate with
436it - and request establishing SockJS connection. Using cookies for
437authorisation in this scenario will result in granting full access to
438SockJS communication with your website from any website. This is a
439classic CSRF attack.
440
441Basically - cookies are not suited for SockJS model. If you want to
442authorise a session - provide a unique token on a page, send it as a
443first thing over SockJS connection and validate it on the server
444side. In essence, this is how cookies work.
445
446
447### Deploying SockJS on Heroku
448
449Long polling is known to cause problems on Heroku, but
450[workaround for SockJS is available](https://github.com/sockjs/sockjs-node/issues/57#issuecomment-5242187).
Note: See TracBrowser for help on using the repository browser.