You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

350 lines
16 KiB

4 years ago
  1. # SockJS-client
  2. [![npm version](https://img.shields.io/npm/v/sockjs-client.svg?style=flat-square)](https://www.npmjs.com/package/sockjs-client)[![Build Status](https://img.shields.io/travis/sockjs/sockjs-client/master.svg?style=flat-square)](https://travis-ci.org/sockjs/sockjs-client)[![Dependencies](https://img.shields.io/david/sockjs/sockjs-client.svg?style=flat-square)](https://david-dm.org/sockjs/sockjs-client)[![Chat](https://img.shields.io/badge/Chat-gitter.im-blue.svg?style=flat-square)](https://gitter.im/sockjs/sockjs-client)
  3. [![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=dW9YdlFsSEI5VzNBVVk5ZS9XT0xaTjJVQkhQMkRkNlZBQURiSWNWMC9jaz0tLXRJM05RbW1tTCt5TlhHaVgycFJUYmc9PQ==--e3ef9b9a9fa071084e6d87874b5fc65b71273821)](https://www.browserstack.com/automate/public-build/dW9YdlFsSEI5VzNBVVk5ZS9XT0xaTjJVQkhQMkRkNlZBQURiSWNWMC9jaz0tLXRJM05RbW1tTCt5TlhHaVgycFJUYmc9PQ==--e3ef9b9a9fa071084e6d87874b5fc65b71273821)
  4. # Supporting SockJS
  5. Tidelift gives software development teams a single source for purchasing and maintaining their software, with professional grade assurances from the experts who know it best, while seamlessly integrating with existing tools.
  6. [Get supported sockjs-client with the Tidelift Subscription](https://tidelift.com/subscription/pkg/npm-sockjs-client?utm_source=npm-sockjs-client&utm_medium=referral&utm_campaign=readme)
  7. # Summary
  8. SockJS is a browser JavaScript library that provides a WebSocket-like
  9. object. SockJS gives you a coherent, cross-browser, Javascript API
  10. which creates a low latency, full duplex, cross-domain communication
  11. channel between the browser and the web server.
  12. Under the hood SockJS tries to use native WebSockets first. If that
  13. fails it can use a variety of browser-specific transport protocols and
  14. presents them through WebSocket-like abstractions.
  15. SockJS is intended to work for all modern browsers and in environments
  16. which don't support the WebSocket protocol -- for example, behind restrictive
  17. corporate proxies.
  18. SockJS-client does require a server counterpart:
  19. * [SockJS-node](https://github.com/sockjs/sockjs-node) is a SockJS
  20. server for Node.js.
  21. Philosophy:
  22. * The API should follow
  23. [HTML5 Websockets API](https://www.w3.org/TR/websockets/) as
  24. closely as possible.
  25. * All the transports must support cross domain connections out of the
  26. box. It's possible and recommended to host a SockJS server on a
  27. different server than your main web site.
  28. * There is support for at least one streaming protocol for every
  29. major browser.
  30. * Streaming transports should work cross-domain and
  31. should support cookies (for cookie-based sticky sessions).
  32. * Polling transports are used as a fallback for old browsers and
  33. hosts behind restrictive proxies.
  34. * Connection establishment should be fast and lightweight.
  35. * No Flash inside (no need to open port 843 - which doesn't work
  36. through proxies, no need to host 'crossdomain.xml', no need
  37. [to wait for 3 seconds](https://github.com/gimite/web-socket-js/issues/49)
  38. in order to detect problems)
  39. Subscribe to
  40. [SockJS mailing list](https://groups.google.com/forum/#!forum/sockjs) for
  41. discussions and support.
  42. # SockJS family
  43. * [SockJS-client](https://github.com/sockjs/sockjs-client) JavaScript client library
  44. * [SockJS-node](https://github.com/sockjs/sockjs-node) Node.js server
  45. * [SockJS-erlang](https://github.com/sockjs/sockjs-erlang) Erlang server
  46. * [SockJS-cyclone](https://github.com/flaviogrossi/sockjs-cyclone) Python/Cyclone/Twisted server
  47. * [SockJS-tornado](https://github.com/MrJoes/sockjs-tornado) Python/Tornado server
  48. * [SockJS-twisted](https://github.com/DesertBus/sockjs-twisted/) Python/Twisted server
  49. * [SockJS-aiohttp](https://github.com/aio-libs/sockjs/) Python/Aiohttp server
  50. * [Spring Framework](https://projects.spring.io/spring-framework) Java [client](https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/web.html#websocket-fallback-sockjs-client) & server
  51. * [vert.x](https://github.com/vert-x/vert.x) Java/vert.x server
  52. * [Xitrum](https://xitrum-framework.github.io/) Scala server
  53. * [Atmosphere Framework](https://github.com/Atmosphere/atmosphere) JavaEE Server, Play Framework, Netty, Vert.x
  54. * [Actix SockJS](https://github.com/fafhrd91/actix-sockjs) Rust Server, Actix Framework
  55. Work in progress:
  56. * [SockJS-ruby](https://github.com/nyarly/sockjs-ruby)
  57. * [SockJS-netty](https://github.com/cgbystrom/sockjs-netty)
  58. * [SockJS-gevent](https://github.com/ksava/sockjs-gevent) ([SockJS-gevent fork](https://github.com/njoyce/sockjs-gevent))
  59. * [pyramid-SockJS](https://github.com/fafhrd91/pyramid_sockjs)
  60. * [wildcloud-websockets](https://github.com/wildcloud/wildcloud-websockets)
  61. * [wai-SockJS](https://github.com/Palmik/wai-sockjs)
  62. * [SockJS-perl](https://github.com/vti/sockjs-perl)
  63. * [SockJS-go](https://github.com/igm/sockjs-go/)
  64. * [syp.biz.SockJS.NET](https://github.com/sypbiz/SockJS.NET) - .NET port of the SockJS client
  65. # Getting Started
  66. SockJS mimics the [WebSockets API](https://www.w3.org/TR/websockets/),
  67. but instead of `WebSocket` there is a `SockJS` Javascript object.
  68. First, you need to load the SockJS JavaScript library. For example, you can
  69. put that in your HTML head:
  70. ```html
  71. <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
  72. ```
  73. After the script is loaded you can establish a connection with the
  74. SockJS server. Here's a simple example:
  75. ```javascript
  76. var sock = new SockJS('https://mydomain.com/my_prefix');
  77. sock.onopen = function() {
  78. console.log('open');
  79. sock.send('test');
  80. };
  81. sock.onmessage = function(e) {
  82. console.log('message', e.data);
  83. sock.close();
  84. };
  85. sock.onclose = function() {
  86. console.log('close');
  87. };
  88. ```
  89. # SockJS-client API
  90. ## SockJS class
  91. Similar to the 'WebSocket' API, the 'SockJS' constructor takes one, or more arguments:
  92. ```javascript
  93. var sockjs = new SockJS(url, _reserved, options);
  94. ```
  95. `url` may contain a query string, if one is desired.
  96. Where `options` is a hash which can contain:
  97. * **server (string)**
  98. String to append to url for actual data connection. Defaults to a random 4 digit number.
  99. * **transports (string OR array of strings)**
  100. Sometimes it is useful to disable some fallback transports. This
  101. option allows you to supply a list transports that may be used by
  102. SockJS. By default all available transports will be used.
  103. * **sessionId (number OR function)**
  104. Both client and server use session identifiers to distinguish connections.
  105. If you specify this option as a number, SockJS will use its random string
  106. generator function to generate session ids that are N-character long
  107. (where N corresponds to the number specified by **sessionId**).
  108. When you specify this option as a function, the function must return a
  109. randomly generated string. Every time SockJS needs to generate a session
  110. id it will call this function and use the returned string directly.
  111. If you don't specify this option, the default is to use the default random
  112. string generator to generate 8-character long session ids.
  113. * **timeout (number)**
  114. Specify a minimum timeout in milliseconds to use for the transport connections.
  115. By default this is dynamically calculated based on the measured RTT and
  116. the number of expected round trips. This setting will establish a minimum,
  117. but if the calculated timeout is higher, that will be used.
  118. Although the 'SockJS' object tries to emulate the 'WebSocket'
  119. behaviour, it's impossible to support all of its features. An
  120. important SockJS limitation is the fact that you're not allowed to
  121. open more than one SockJS connection to a single domain at a time.
  122. This limitation is caused by an in-browser limit of outgoing
  123. connections - usually [browsers don't allow opening more than two
  124. outgoing connections to a single domain](https://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser). A single SockJS session
  125. requires those two connections - one for downloading data, the other for
  126. sending messages. Opening a second SockJS session at the same time
  127. would most likely block, and can result in both sessions timing out.
  128. Opening more than one SockJS connection at a time is generally a
  129. bad practice. If you absolutely must do it, you can use
  130. multiple subdomains, using a different subdomain for every
  131. SockJS connection.
  132. # Supported transports, by browser (html served from http:// or https://)
  133. _Browser_ | _Websockets_ | _Streaming_ | _Polling_
  134. ----------------|------------------|-------------|-------------------
  135. IE 6, 7 | no | no | jsonp-polling
  136. IE 8, 9 (cookies=no) | no | xdr-streaming &dagger; | xdr-polling &dagger;
  137. IE 8, 9 (cookies=yes)| no | iframe-htmlfile | iframe-xhr-polling
  138. IE 10 | rfc6455 | xhr-streaming | xhr-polling
  139. Chrome 6-13 | hixie-76 | xhr-streaming | xhr-polling
  140. Chrome 14+ | hybi-10 / rfc6455| xhr-streaming | xhr-polling
  141. Firefox <10 | no &Dagger; | xhr-streaming | xhr-polling
  142. Firefox 10+ | hybi-10 / rfc6455| xhr-streaming | xhr-polling
  143. Safari 5.x | hixie-76 | xhr-streaming | xhr-polling
  144. Safari 6+ | rfc6455 | xhr-streaming | xhr-polling
  145. Opera 10.70+ | no &Dagger; | iframe-eventsource | iframe-xhr-polling
  146. Opera 12.10+ | rfc6455 | xhr-streaming | xhr-polling
  147. Konqueror | no | no | jsonp-polling
  148. * **&dagger;**: IE 8+ supports [XDomainRequest][^9], which is
  149. essentially a modified AJAX/XHR that can do requests across
  150. domains. But unfortunately it doesn't send any cookies, which
  151. makes it inappropriate for deployments when the load balancer uses
  152. JSESSIONID cookie to do sticky sessions.
  153. * **&Dagger;**: Firefox 4.0 and Opera 11.00 and shipped with disabled
  154. Websockets "hixie-76". They can still be enabled by manually
  155. changing a browser setting.
  156. # Supported transports, by browser (html served from file://)
  157. Sometimes you may want to serve your html from "file://" address - for
  158. development or if you're using PhoneGap or similar technologies. But
  159. due to the Cross Origin Policy files served from "file://" have no
  160. Origin, and that means some of SockJS transports won't work. For this
  161. reason the SockJS transport table is different than usually, major
  162. differences are:
  163. _Browser_ | _Websockets_ | _Streaming_ | _Polling_
  164. ----------------|---------------|--------------------|-------------------
  165. IE 8, 9 | same as above | iframe-htmlfile | iframe-xhr-polling
  166. Other | same as above | iframe-eventsource | iframe-xhr-polling
  167. # Supported transports, by name
  168. _Transport_ | _References_
  169. ---------------------|---------------
  170. websocket (rfc6455) | [rfc 6455][^10]
  171. websocket (hixie-76) | [draft-hixie-thewebsocketprotocol-76][^1]
  172. websocket (hybi-10) | [draft-ietf-hybi-thewebsocketprotocol-10][^2]
  173. xhr-streaming | Transport using [Cross domain XHR][^5] [streaming][^7] capability (readyState=3).
  174. xdr-streaming | Transport using [XDomainRequest][^9] [streaming][^7] capability (readyState=3).
  175. eventsource | [EventSource/Server-sent events][^4].
  176. iframe-eventsource | [EventSource/Server-sent events][^4] used from an [iframe via postMessage][^3].
  177. htmlfile | [HtmlFile][^8].
  178. iframe-htmlfile | [HtmlFile][^8] used from an [iframe via postMessage][^3].
  179. xhr-polling | Long-polling using [cross domain XHR][^5].
  180. xdr-polling | Long-polling using [XDomainRequest][^9].
  181. iframe-xhr-polling | Long-polling using normal AJAX from an [iframe via postMessage][^3].
  182. jsonp-polling | Slow and old fashioned [JSONP polling][^6]. This transport will show "busy indicator" (aka: "spinning wheel") when sending data.
  183. [^1]: https://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76
  184. [^2]: https://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10
  185. [^3]: https://developer.mozilla.org/en/DOM/window.postMessage
  186. [^4]: https://html.spec.whatwg.org/multipage/comms.html#server-sent-events
  187. [^5]: https://secure.wikimedia.org/wikipedia/en/wiki/XMLHttpRequest#Cross-domain_requests
  188. [^6]: https://secure.wikimedia.org/wikipedia/en/wiki/JSONP
  189. [^7]: http://www.debugtheweb.com/test/teststreaming.aspx
  190. [^8]: http://cometdaily.com/2007/11/18/ie-activexhtmlfile-transport-part-ii/
  191. [^9]: https://blogs.msdn.microsoft.com/ieinternals/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds/
  192. [^10]: https://www.rfc-editor.org/rfc/rfc6455.txt
  193. # Connecting to SockJS without the client
  194. Although the main point of SockJS is to enable browser-to-server
  195. connectivity, it is possible to connect to SockJS from an external
  196. application. Any SockJS server complying with 0.3 protocol does
  197. support a raw WebSocket url. The raw WebSocket url for the test server
  198. looks like:
  199. * ws://localhost:8081/echo/websocket
  200. You can connect any WebSocket RFC 6455 compliant WebSocket client to
  201. this url. This can be a command line client, external application,
  202. third party code or even a browser (though I don't know why you would
  203. want to do so).
  204. # Deployment
  205. You should use a version of sockjs-client
  206. that supports the protocol used by your server. For example:
  207. ```html
  208. <script src="https://cdn.jsdelivr.net/npm/sockjs-client@1/dist/sockjs.min.js"></script>
  209. ```
  210. For server-side deployment tricks, especially about load balancing and
  211. session stickiness, take a look at the
  212. [SockJS-node readme](https://github.com/sockjs/sockjs-node#readme).
  213. # Development and testing
  214. SockJS-client needs [node.js](https://nodejs.org/) for running a test
  215. server and JavaScript minification. If you want to work on
  216. SockJS-client source code, checkout the git repo and follow these
  217. steps:
  218. cd sockjs-client
  219. npm install
  220. To generate JavaScript, run:
  221. gulp browserify
  222. To generate minified JavaScript, run:
  223. gulp browserify:min
  224. Both commands output into the `build` directory.
  225. ## Testing
  226. Automated testing provided by:
  227. <a href="https://browserstack.com"><img src="img/Browserstack-logo@2x.png" height="50"></a>
  228. Once you've compiled the SockJS-client you may want to check if your changes
  229. pass all the tests.
  230. npm run test:browser_local
  231. This will start [karma](https://karma-runner.github.io) and a test support server.
  232. # Browser Quirks
  233. There are various browser quirks which we don't intend to address:
  234. * Pressing ESC in Firefox, before Firefox 20, closes the SockJS connection. For a workaround
  235. and discussion see [#18](https://github.com/sockjs/sockjs-client/issues/18).
  236. * `jsonp-polling` transport will show a "spinning wheel" (aka. "busy indicator")
  237. when sending data.
  238. * You can't open more than one SockJS connection to one domain at the
  239. same time due to [the browser's limit of concurrent connections](https://stackoverflow.com/questions/985431/max-parallel-http-connections-in-a-browser)
  240. (this limit is not counting native WebSocket connections).
  241. * Although SockJS is trying to escape any strange Unicode characters
  242. (even invalid ones - [like surrogates \xD800-\xDBFF](https://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Surrogates) or [\xFFFE and \xFFFF](https://en.wikipedia.org/wiki/Unicode#Character_General_Category))
  243. it's advisable to use only valid characters. Using invalid
  244. characters is a bit slower, and may not work with SockJS servers
  245. that have proper Unicode support.
  246. * Having a global function called `onmessage` or such is probably a
  247. bad idea, as it could be called by the built-in `postMessage` API.
  248. * From SockJS' point of view there is nothing special about
  249. SSL/HTTPS. Connecting between unencrypted and encrypted sites
  250. should work just fine.
  251. * Although SockJS does its best to support both prefix and cookie based
  252. sticky sessions, the latter may not work well cross-domain with
  253. browsers that don't accept third-party cookies by default (Safari).
  254. In order to get around this make sure you're connecting to SockJS
  255. from the same parent domain as the main site. For example
  256. 'sockjs.a.com' is able to set cookies if you're connecting from
  257. 'www.a.com' or 'a.com'.
  258. * Trying to connect from secure "https://" to insecure "http://" is
  259. not a good idea. The other way around should be fine.
  260. * Long polling is known to cause problems on Heroku, but a
  261. [workaround for SockJS is available](https://github.com/sockjs/sockjs-node/issues/57#issuecomment-5242187).
  262. * SockJS [websocket transport is more stable over SSL](https://github.com/sockjs/sockjs-client/issues/94). If
  263. you're a serious SockJS user then consider using SSL
  264. ([more info](https://www.ietf.org/mail-archive/web/hybi/current/msg01605.html)).