@@ -37195,6 +37195,64 @@ supported in all browsers yet and may be precluded by restrictive network proxie
37195
37195
This is why Spring provides fallback options that emulate the WebSocket API as close
37196
37196
as possible based on the https://github.com/sockjs/sockjs-protocol[SockJS protocol].
37197
37197
37198
+ [[websocket-fallback-sockjs-overview]]
37199
+ ==== Overview of SockJS
37200
+
37201
+ The goal of SockJS is to let applications use a WebSocket API but fall back to
37202
+ non-WebSocket alternatives when necessary at runtime, i.e. without the need to
37203
+ change application code.
37204
+
37205
+ SockJS consists of:
37206
+
37207
+ * The https://github.com/sockjs/sockjs-protocol[SockJS protocol]
37208
+ defined in the form of executable
37209
+ http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[narrated tests].
37210
+ * The https://github.com/sockjs/sockjs-client[SockJS client] - a JavaScript library for use in browsers.
37211
+ * SockJS server implementations including one in the Spring Framework `spring-websocket` module.
37212
+
37213
+ SockJS is designed for use in browsers. It goes to great lengths
37214
+ to support a wide range of browser versions using a variety of techniques.
37215
+ For the full list of SockJS transport types and browsers see the
37216
+ https://github.com/sockjs/sockjs-client[SockJS client] page. Transports
37217
+ fall in 3 general categories: WebSocket, HTTP Streaming, and HTTP Long Polling.
37218
+ For an overview of these categories see
37219
+ https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates/[this blog post].
37220
+
37221
+ The SockJS client begins by sending `"GET /info"` to
37222
+ obtain basic information from the server. After that it must decide what transport
37223
+ to use. If possible WebSocket is used. If not, in most browsers
37224
+ there is at least one HTTP streaming option and if not then HTTP (long)
37225
+ polling is used.
37226
+
37227
+ All transport requests have the following URL structure:
37228
+ ----
37229
+ http://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport}
37230
+ ----
37231
+
37232
+ * `{server-id}` - useful for routing requests in a cluster but not used otherwise.
37233
+ * `{session-id}` - correlates HTTP requests belonging to a SockJS session.
37234
+ * `{transport}` - indicates the transport type, e.g. "websocket", "xhr-streaming", etc.
37235
+
37236
+ The WebSocket transport needs only a single HTTP request to do the WebSocket handshake.
37237
+ All messages thereafter are exchanged on that socket.
37238
+
37239
+ HTTP transports require more requests. Ajax/XHR streaming for example relies on
37240
+ one long-running request for server-to-client messages and additional HTTP POST
37241
+ requests for client-to-server messages. Long polling is similar except it
37242
+ ends the current request after each server-to-client send.
37243
+
37244
+ SockJS adds minimal message framing. For example the server sends the letter +o+
37245
+ ("open" frame) initially, messages are sent as +a["message1","message2"]+
37246
+ (JSON-encoded array), the letter +h+ ("heartbeat" frame) if no messages flow
37247
+ for 25 seconds by default, and the letter +c+ ("close" frame) to close the session.
37248
+
37249
+ To learn more run an example in a browser and watch HTTP requests.
37250
+ The SockJS client allows fixing the list of transports so it is possible to
37251
+ see each transport one at a time. The SockJS client also provides a debug flag
37252
+ which enables helpful messages in the browser console. On the server side enable
37253
+ TRACE logging for `org.springframework.web.socket`.
37254
+ For even more detail refer to the SockJS protocol
37255
+ http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[narrated test].
37198
37256
37199
37257
37200
37258
[[websocket-fallback-sockjs-enable]]
@@ -37259,22 +37317,6 @@ https://github.com/sockjs/sockjs-client[sockjs-client] page and the list of
37259
37317
transport types supported by browser. The client also provides several
37260
37318
configuration options, for example, to specify which transports to include.
37261
37319
37262
- [[websocket-fallback-sockjs-transport]]
37263
- ==== SockJS Transports
37264
-
37265
- The SockJS client simulates the WebSocket API in a wide range of browsers.
37266
- For the full list of transports by browser see the
37267
- https://github.com/sockjs/sockjs-client[SockJS client] page. The transport types
37268
- fall in 3 categories: WebSocket, HTTP Streaming, and HTTP Long Polling. For more
37269
- background on those techniques see
37270
- https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates/[this blog post].
37271
- An important goal of SockJS is to support at least one streaming transport
37272
- per browser, for efficiency reasons, but when necessary fall back on
37273
- long polling.
37274
-
37275
- The next few sections cover various aspects of confugring and using SockJS
37276
- in Spring applications.
37277
-
37278
37320
[[websocket-fallback-xhr-vs-iframe]]
37279
37321
==== HTTP Streaming in IE 8, 9: Ajax/XHR vs IFrame
37280
37322
@@ -37357,7 +37399,7 @@ https://github.com/sockjs/sockjs-client[SockJS client] page.
37357
37399
====
37358
37400
37359
37401
[[websocket-fallback-sockjs-heartbeat]]
37360
- ==== Heartbeat Support in SockJS
37402
+ ==== Heartbeat Messages
37361
37403
37362
37404
The SockJS protocol requires servers to send heartbeat messages to preclude proxies
37363
37405
from concluding a connection is hung. The Spring SockJS configuiration has a property
@@ -37378,7 +37420,7 @@ with default settings based on the number of available processors. Applications
37378
37420
should consider customizing the settings according to their specific needs.
37379
37421
37380
37422
[[websocket-fallback-sockjs-servlet3-async]]
37381
- ==== SockJS and Servlet 3 Async Support
37423
+ ==== Servlet 3 Async Requests
37382
37424
37383
37425
HTTP streaming and HTTP long polling SockJS transports require a connection to remain
37384
37426
open longer than usual. For an overview of these techniques see
@@ -37406,53 +37448,27 @@ log category to TRACE.
37406
37448
====
37407
37449
37408
37450
[[websocket-fallback-cors]]
37409
- ==== SockJS and CORS
37451
+ ==== CORS Headers for SockJS Requests
37410
37452
37411
37453
The SockJS protocol uses CORS for cross-domain support in the XHR streaming and
37412
- XHR polling transports. CORS headers are automatically added to SockJS requests
37413
- for transports that require it as well as for the initial `"/info"` request.
37454
+ polling transports. Therefore CORS headers are added automatically unless the
37455
+ presence of CORS headers in the response is detected. So if an application is
37456
+ already configured to provide CORS support, e.g. through a Servlet Filter,
37457
+ Spring's SockJsService will skip this part.
37414
37458
37415
- Spring's `SockJsServce` implementation checks for the presence of the CORS
37416
- `"Access-Control-Allow-Origin"` header in the response. If present, no new CORS
37417
- headers are added, essentially assuming that CORS support is configured
37418
- centrally, e.g. through a Servlet Filter. Otherwise the following are added:
37459
+ The following is the list of headers and values expected by SockJS:
37419
37460
37420
37461
* `"Access-Control-Allow-Origin"` - intitialized from the value of the "origin" request header or "*".
37421
37462
* `"Access-Control-Allow-Credentials"` - always set to `true`.
37422
37463
* `"Access-Control-Request-Headers"` - initialized from values from the equivalent request header.
37423
37464
* `"Access-Control-Allow-Methods"` - the HTTP methods a transport supports (see `TransportType` enum).
37424
37465
* `"Access-Control-Max-Age"` - set to 31536000 (1 year).
37425
37466
37426
- For the exact implementation, see `addCorsHeaders` in `AbstractSockJsService`.
37427
-
37428
- [[websocket-fallback-sockjs-explained]]
37429
- ==== How SockJS Works
37430
- This is a question beyond the scope of this document. The SockJS protocol
37431
- is defined in the form of a Python
37432
- https://github.com/sockjs/sockjs-protocol/blob/master/sockjs-protocol-0.3.3.py[test suite],
37433
- with narrative in comments. There is an
37434
- http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html[HTML formatted version]
37435
- of the test showing narrative on the right and client code on the left.
37436
-
37437
- The SockJS client begins with an initial `"/info"` request to obtain basic
37438
- information from the server. Then the client selects a transport and sends
37439
- a series of session requests:
37440
-
37441
- ----
37442
- http://host:port/{sockjs-endpoint}/{server-id}/{session-id}/{transport}
37443
- ----
37444
-
37445
- The WebSocket transport type only needs a single HTTP connection for the handshake.
37446
- HTTP-based transports use one connection for sending messages from server to client
37447
- and separate requests for sending messages from client to server.
37448
- The session id is used to correlate HTTP requests belonging to the same SockJS
37449
- session. The server id is not used in the protocol but is added to help in
37450
- clustered environments.
37467
+ For the exact implementation see `addCorsHeaders` in `AbstractSockJsService` as well
37468
+ as the `TransportType` enum in the source code.
37451
37469
37452
- The SockJS protocol requires minimal message framing. The server for examples sends
37453
- an "open frame" (the letter +o+), a "heartbeat frame" (the letter +h+), or a
37454
- "close frame" (the letter +c+); while the client sends messages as a JSON-encoded
37455
- array prepended with the letter `a` (e.g. +a["message1","message2"]+).
37470
+ Alternatively if the CORS configuration allows it consider excluding URLs with the
37471
+ SockJS endpoint prefix thus letting Spring's SockJsService handle it.
37456
37472
37457
37473
37458
37474
[[websocket-stomp]]
0 commit comments