diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/config/annotation/SockJsServiceRegistration.java b/spring-websocket/src/main/java/org/springframework/web/socket/config/annotation/SockJsServiceRegistration.java
index 20507b4e762..28a29d8c6bf 100644
--- a/spring-websocket/src/main/java/org/springframework/web/socket/config/annotation/SockJsServiceRegistration.java
+++ b/spring-websocket/src/main/java/org/springframework/web/socket/config/annotation/SockJsServiceRegistration.java
@@ -78,8 +78,9 @@ public class SockJsServiceRegistration {
* "foreign" domain) from an invisible iframe. Code run from this iframe
* doesn't need to worry about cross-domain issues since it is running from
* a domain local to the SockJS server. The iframe does need to load the
- * SockJS javascript client library and this option allows configuring its
- * url.
+ * SockJS javascript client library and this option allows configuring its url.
+ * See the reference documentation for more details on this.
+ *
*
By default this is set to point to
* "https://d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.4.min.js".
*/
@@ -108,10 +109,12 @@ public class SockJsServiceRegistration {
* from clients with a "cookie_needed" boolean property that indicates whether the use
* of a JSESSIONID cookie is required for the application to function correctly, e.g.
* for load balancing or in Java Servlet containers for the use of an HTTP session.
+ *
*
This is especially important for IE 8,9 that support XDomainRequest -- a modified
* AJAX/XHR -- that can do requests across domains but does not send any cookies. In
* those cases, the SockJS client prefers the "iframe-htmlfile" transport over
* "xdr-streaming" in order to be able to send cookies.
+ *
*
The default value is "true" to maximize the chance for applications to work
* correctly in IE 8,9 with support for cookies (and the JSESSIONID cookie in
* particular). However, an application can choose to set this to "false" if the use
diff --git a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/support/AbstractSockJsService.java b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/support/AbstractSockJsService.java
index 1baf7e88f4d..ae9639ed43c 100644
--- a/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/support/AbstractSockJsService.java
+++ b/spring-websocket/src/main/java/org/springframework/web/socket/sockjs/support/AbstractSockJsService.java
@@ -44,6 +44,7 @@ import org.springframework.util.StringUtils;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.sockjs.SockJsException;
import org.springframework.web.socket.sockjs.SockJsService;
+import org.springframework.web.util.UriComponentsBuilder;
/**
* An abstract base class for {@link SockJsService} implementations that provides SockJS
@@ -106,8 +107,9 @@ public abstract class AbstractSockJsService implements SockJsService {
* "foreign" domain) from an invisible iframe. Code run from this iframe
* doesn't need to worry about cross-domain issues since it is running from
* a domain local to the SockJS server. The iframe does need to load the
- * SockJS javascript client library and this option allows configuring its
- * url.
+ * SockJS javascript client library and this option allows configuring that url.
+ * For more details see the reference documentation.
+ *
*
By default this is set to point to
* "https://d1fxtkz8shb9d2.cloudfront.net/sockjs-0.3.4.min.js".
*/
@@ -146,13 +148,16 @@ public abstract class AbstractSockJsService implements SockJsService {
* clients with a "cookie_needed" boolean property that indicates whether the use of a
* JSESSIONID cookie is required for the application to function correctly, e.g. for
* load balancing or in Java Servlet containers for the use of an HTTP session.
+ *
*
This is especially important for IE 8,9 that support XDomainRequest -- a modified
* AJAX/XHR -- that can do requests across domains but does not send any cookies. In
* those cases, the SockJS client prefers the "iframe-htmlfile" transport over
* "xdr-streaming" in order to be able to send cookies.
+ *
*
The SockJS protocol also expects a SockJS service to echo back the JSESSIONID
* cookie when this property is set to true. However, when running in a Servlet
* container this is not necessary since the container takes care of it.
+ *
*
The default value is "true" to maximize the chance for applications to work
* correctly in IE 8,9 with support for cookies (and the JSESSIONID cookie in
* particular). However, an application can choose to set this to "false" if
diff --git a/src/asciidoc/index.adoc b/src/asciidoc/index.adoc
index 923990103c6..cacfd865380 100644
--- a/src/asciidoc/index.adoc
+++ b/src/asciidoc/index.adoc
@@ -37188,7 +37188,7 @@ or WebSocket XML namespace:
[[websocket-fallback]]
-=== Fallback Options
+=== SockJS Fallback Options
As explained in the <>, WebSocket is not
supported in all browsers yet and may be precluded by restrictive network proxies.
This is why Spring provides fallback options that emulate the WebSocket API as close
@@ -37258,6 +37258,102 @@ https://github.com/sockjs/sockjs-client[sockjs-client] page and the list of
transport types supported by browser. The client also provides several
configuration options, for example, to specify which transports to include.
+[[websocket-fallback-sockjs-transport]]
+==== SockJS Transports
+
+The SockJS client simulates the WebSocket API in a wide range of browsers.
+For the full list of transports by browser see the
+https://github.com/sockjs/sockjs-client[SockJS client] page. The transport types
+fall in 3 categories: WebSocket, HTTP Streaming, and HTTP Long Polling. For more
+background on those techniques see
+https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates/[this blog post].
+An important goal of SockJS is to support at least one streaming transport
+per browser, for efficiency reasons, but when necessary fall back on
+long polling.
+
+The next few sections cover various aspects of confugring and using SockJS
+in Spring applications.
+
+[[websocket-fallback-xhr-vs-iframe]]
+==== HTTP Streaming in IE 8, 9: Ajax/XHR vs IFrame
+
+Internet Explorer 8 and 9 are and will remain common for some time. They are
+a key reason for having SockJS. This section covers important
+considerations about running in those browsers.
+
+SockJS client supports Ajax/XHR streaming in IE 8, 9 via Microsoft's
+http://blogs.msdn.com/b/ieinternals/archive/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds.aspx[XDomainRequest].
+That works across domains but does not support sending cookies.
+Cookies are very often essential for Java applications.
+However since the SockJS client can be used with many server
+types (not just Java ones), it needs to know whether cookies do matter.
+If so the SockJS client prefers Ajax/XHR for streaming or otherwise it
+relies on a iframe-based technique.
+
+The very first `"/info"` request from the SockJS client is a request for
+information that can influence the client's choice of transports.
+One of those details is whether the server application relies on cookies,
+e.g. for authentication purposes or clustering with sticky sessions.
+Spring's SockJS support includes a property called `sessionCookieNeeded`.
+It is enabled by default since most Java applications rely on the `JSESSIONID`
+cookie. If your application does not need it, you can turn off this option
+and the SockJS client should choose the `xhr-streaming` transport in IE 8 and 9.
+
+If you do use an iframe-based transport, and in any case, it is good to know
+that browsers can be instructed to block the use of iframes on a given page by
+setting the HTTP response header `X-Frame-Options` to `DENY`,
+`SAMEORIGIN`, or `ALLOW-FROM `. This is used to prevent
+https://www.owasp.org/index.php/Clickjacking[clickjacking].
+
+[NOTE]
+====
+Spring Security 3.2+ provides support for setting `X-Frame-Options` on every
+response. By default the Spring Security Java config sets it to `DENY`.
+In 3.2 the Spring Security XML namespace does not set that header by default
+but may be configured to do so, and in the future it may set it by default.
+
+See http://docs.spring.io/spring-security/site/docs/3.2.2.RELEASE/reference/htmlsingle/#headers[Section 7.1. "Default Security Headers"]
+of the Spring Security documentation for details no how to configure the
+setting of the `X-Frame-Options` header. You may also check or watch
+https://jira.spring.io/browse/SEC-2501[SEC-2501] for additional background.
+====
+
+If your application adds the `X-Frame-Options` response header (as it should!)
+and relies on an iframe-based transport, you will need to set the header value to
+`SAMEORIGIN` or `ALLOW-FROM `. Along with that the Spring SockJS
+support also needs to know the location of the SockJS client because it is loaded
+from the iframe. By default the iframe is set to download the SockJS client
+from a CDN location. It is a good idea to configure this option to
+a URL from the same origin as the application.
+
+In Java config this can be done as shown below. The XML namespace provides a
+similar option on the `` element:
+
+[source,java,indent=0]
+[subs="verbatim,quotes"]
+----
+ @Configuration
+ @EnableWebSocket
+ public class WebSocketConfig implements WebSocketConfigurer {
+
+ @Override
+ public void registerStompEndpoints(StompEndpointRegistry registry) {
+ registry.addEndpoint("/portfolio").withSockJS()
+ .setClientLibraryUrl("http://localhost:8080/myapp/js/sockjs-client.js");
+ }
+
+ // ...
+
+ }
+----
+
+[NOTE]
+====
+During initial development, do enable the SockJS client `devel` mode that prevents
+the browser from caching SockJS requests (like the iframe) that would otherwise
+be cached. For details on how to enable it see the
+https://github.com/sockjs/sockjs-client[SockJS client] page.
+====
[[websocket-fallback-sockjs-servlet3-async]]