diff --git a/src/docs/asciidoc/web/websocket-intro.adoc b/src/docs/asciidoc/web/websocket-intro.adoc new file mode 100644 index 0000000000..b74775706c --- /dev/null +++ b/src/docs/asciidoc/web/websocket-intro.adoc @@ -0,0 +1,95 @@ +[[websocket-intro]] += Introduction + +The WebSocket protocol http://tools.ietf.org/html/rfc6455[RFC 6455] provides a standardized +way to establish a full-duplex, two-way communication channel between client and server +over a single TCP connection. It is a different TCP protocol from HTTP but is designed to +work over HTTP, using ports 80 and 443 and allowing re-use of existing firewall rules. + +A WebSocket interaction begins with an HTTP request that uses the HTTP `"Upgrade"` header +to upgrade, or in this case to switch, to the WebSocket protocol: + +[subs="quotes"] +---- +GET /spring-websocket-portfolio/portfolio HTTP/1.1 +Host: localhost:8080 +**Upgrade: websocket** +**Connection: Upgrade** +Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg== +Sec-WebSocket-Protocol: v10.stomp, v11.stomp +Sec-WebSocket-Version: 13 +Origin: http://localhost:8080 +---- + +Instead of the usual 200 status code, a server with WebSocket support returns: + +[subs="quotes"] +---- +**HTTP/1.1 101 Switching Protocols** +Upgrade: websocket +Connection: Upgrade +Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0= +Sec-WebSocket-Protocol: v10.stomp +---- + +After a successful handshake the TCP socket underlying the HTTP upgrade request remains +open for both client and server to continue to send and receive messages. + +A complete introduction of how WebSockets work is beyond the scope of this document. +Please read RFC 6455, the WebSocket chapter of HTML5, or one of many introductions and +tutorials on the Web. + +Note that if a WebSocket server is running behind a web server (e.g. nginx) you will +likely need to configure it to pass WebSocket upgrade requests on to the WebSocket +server. Likewise if the application runs in a cloud environment, check the +instructions of the cloud provider related to WebSocket support. + + + + +[[websocket-intro-architecture]] +== HTTP vs WebSocket + +Even though WebSocket is designed to be HTTP compatible and starts with an HTTP request, +it is important to understand that the two protocols lead to very different +architectures and application programming models. + +In HTTP and REST, an application is modeled as many URLs. To interact with the application +clients access those URLs, request-response style. Servers route requests to the +appropriate handler based on the HTTP URL, method, and headers. + +By contrast in WebSockets there is usually just one URL for the initial connect and +subsequently all application messages flow on that same TCP connection. This points to +an entirely different asynchronous, event-driven, messaging architecture. + +WebSocket is also a low-level transport protocol which unlike HTTP does not prescribe +any semantics to the content of messages. That means there is no way to route or process +a message unless client and server agree on message semantics. + +WebSocket clients and servers can negotiate the use of a higher-level, messaging protocol +(e.g. STOMP), via the `"Sec-WebSocket-Protocol"` header on the HTTP handshake request, +or in the absence of that they need to come up with their own conventions. + + + +[[websocket-intro-when-to-use]] +== When to use it? + +WebSockets can make a web page dynamic and interactive. However in many cases +a combination of Ajax and HTTP streaming and/or long polling could provide a simple and +effective solution. + +For example news, mail, and social feeds need to update dynamically but it may be +perfectly okay to do so every few minutes. Collaboration, games, and financial apps on +the other hand need to be much closer to real time. + +Latency alone is not a deciding factor. If the volume of messages is relatively low (e.g. +monitoring network failures) HTTP streaming or polling may provide an effective solution. +It is the combination of low latency, high frequency and high volume that make the best +case for the use WebSocket. + +Keep in mind also that over the Internet, restrictive proxies outside your control, +may preclude WebSocket interactions either because they are not configured to pass on the +`Upgrade` header or because they close long lived connections that appear idle? This +means that the use of WebSocket for internal applications within the firewall is a more +straight-forward decision than it is for public facing applications. diff --git a/src/docs/asciidoc/web/websocket.adoc b/src/docs/asciidoc/web/websocket.adoc index c88f21cb38..da679e1921 100644 --- a/src/docs/asciidoc/web/websocket.adoc +++ b/src/docs/asciidoc/web/websocket.adoc @@ -2,163 +2,12 @@ = WebSockets :doc-spring-security: {doc-root}/spring-security/site/docs/current/reference -This part of the reference documentation covers support for Servlet stack WebSocket -messaging, SockJS-based fallback options, and the use of STOMP as a WebSocket messaging -sub-protocol. - - - - -[[websocket-intro]] -== Introduction - -The WebSocket protocol http://tools.ietf.org/html/rfc6455[RFC 6455] provides a standardized -way to establish a full-duplex, two-way communication channel between client and server -over a single TCP connection. It is a different TCP protocol from HTTP but is designed to -work over HTTP ports 80 and 443 thus allowing use of existing firewall rules. - -A WebSocket interaction begins with an HTTP compatible handshake request that uses the -HTTP `"Upgrade"` header to request switching to the WebSocket protocol: - -[subs="quotes"] ----- -GET /spring-websocket-portfolio/portfolio HTTP/1.1 -Host: localhost:8080 -**Upgrade: websocket** -**Connection: Upgrade** -Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg== -Sec-WebSocket-Protocol: v10.stomp, v11.stomp -Sec-WebSocket-Version: 13 -Origin: http://localhost:8080 ----- - -The response from a server with WebSocket support: - -[subs="quotes"] ----- -**HTTP/1.1 101 Switching Protocols** -Upgrade: websocket -Connection: Upgrade -Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0= -Sec-WebSocket-Protocol: v10.stomp ----- - -After a successful handshake the TCP socket underlying the HTTP upgrade request remains -open and both client and server can use send and receive messages. - -If you Servlet container is running behind a web server (e.g. nginx) you will likely need -to configure it to send WebSocket upgrades to the backend server. Likewise if running in a -cloud environment check the instructions for WebSocket support of your cloud provider. - -Beyond that, what do you do about restrictive proxies, outside your control, that preclude -WebSocket interactions either because they are not configured to pass on the `Upgrade` -header or because they close long lived connections that appear idle? The answer to this -is WebSocket emulation that tries to use WebSocket first and then falls back HTTP-based -techniques that WebSocket-like communication. See <>. - - - - -WebSocket brings up important design considerations that are important to recognize -early on, especially in contrast to what we know about building web applications today. - -Today REST is a widely accepted, understood, and supported -architecture for building web applications. It is an architecture that relies -on having many URLs (__nouns__), a handful of HTTP methods (__verbs__), and -other principles such as using hypermedia (__links__), remaining stateless, etc. - -By contrast a WebSocket application may use a single URL only for the -initial HTTP handshake. All messages thereafter share and flow on the -same TCP connection. This points to an entirely different, asynchronous, -event-driven, messaging architecture. One that is much closer -to traditional messaging applications (e.g. JMS, AMQP). - -Spring Framework 4 includes a new `spring-messaging` module with key -abstractions from the -http://projects.spring.io/spring-integration/[Spring Integration] project -such as `Message`, `MessageChannel`, `MessageHandler`, and others that can serve as -a foundation for such a messaging architecture. The module also includes a -set of annotations for mapping messages to methods, similar to the Spring MVC -annotation based programming model. - - - -[[websocket-intro-sub-protocol]] -=== WebSocket Sub-Protocol - -WebSocket does imply a __messaging architecture__ but does not mandate the -use of any specific __messaging protocol__. It is a very thin layer over TCP -that transforms a stream of bytes into a stream of messages -(either text or binary) and not much more. It is up to applications -to interpret the meaning of a message. - -Unlike HTTP, which is an application-level protocol, in the WebSocket protocol -there is simply not enough information in an incoming message for a framework -or container to know how to route it or process it. Therefore WebSocket is arguably -too low level for anything but a very trivial application. It can be done, but -it will likely lead to creating a framework on top. This is comparable to how -most web applications today are written using a web framework rather than the -Servlet API alone. - -For this reason the WebSocket RFC defines the use of -http://tools.ietf.org/html/rfc6455#section-1.9[sub-protocols]. -During the handshake, the client and server can use the header -`Sec-WebSocket-Protocol` to agree on a sub-protocol, i.e. a higher, application-level -protocol to use. The use of a sub-protocol is not required, but -even if not used, applications will still need to choose a message -format that both the client and server can understand. That format can be custom, -framework-specific, or a standard messaging protocol. - -The Spring Framework provides support for using -http://stomp.github.io/stomp-specification-1.2.html#Abstract[STOMP] -- a simple, messaging protocol -originally created for use in scripting languages with frames inspired -by HTTP. STOMP is widely supported and well suited for use over -WebSocket and over the web. - - - -[[websocket-intro-when-to-use]] -=== Do I Use WebSocket? - -With all the design considerations surrounding the use of WebSocket, it is -reasonable to ask, "When is it appropriate to use?". - -The best fit for WebSocket is in web applications where the client and -server need to exchange events at high frequency and with low latency. Prime -candidates include, but are not limited to, applications in finance, games, -collaboration, and others. Such applications are both very sensitive to time -delays and also need to exchange a wide variety of messages at a high -frequency. - -For other application types, however, this may not be the case. -For example, a news or social feed that shows breaking news as it becomes -available may be perfectly okay with simple polling once every few minutes. -Here latency is important, but it is acceptable if the news takes a -few minutes to appear. - -Even in cases where latency is crucial, if the volume of messages is -relatively low (e.g. monitoring network failures) the use of -https://spring.io/blog/2012/05/08/spring-mvc-3-2-preview-techniques-for-real-time-updates[long polling] -should be considered as a relatively simple alternative that -works reliably and is comparable in terms of efficiency (again assuming the volume of -messages is relatively low). - -It is the combination of both low latency and high frequency of messages that can make -the use of the WebSocket protocol critical. Even in such applications, -the choice remains whether all client-server -communication should be done through WebSocket messages as opposed to using -HTTP and REST. The answer is going to vary by application; however, it is likely -that some functionality may be exposed over both WebSocket and as a REST API in -order to provide clients with alternatives. Furthermore, a REST API call may need -to broadcast a message to interested clients connected via WebSocket. - -The Spring Framework allows `@Controller` and `@RestController` classes to have both -HTTP request handling and WebSocket message handling methods. -Furthermore, a Spring MVC request handling method, or any application -method for that matter, can easily broadcast a message to all interested -WebSocket clients or to a specific user. +This part of the reference documentation covers support for Servlet stack, WebSocket +messaging that includes raw WebSocket interactions, WebSocket emulation via SockJS, and +pub-sub messaging via STOMP as a sub-protocol over WebSocket. +include::websocket-intro.adoc[leveloffset=+1] [[websocket-server]] @@ -620,12 +469,16 @@ XML configuration equivalent: [[websocket-fallback]] == SockJS Fallback -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 -as possible based on the https://github.com/sockjs/sockjs-protocol[SockJS protocol] -(version 0.3.3). +Over the public Internet, restrictive proxies outside your control may preclude WebSocket +interactions either because they are not configured to pass on the `Upgrade` header or +because they close long lived connections that appear idle. +The solution to this problem is WebSocket emulation, i.e. attempting to use WebSocket +first and then falling back on HTTP-based techniques that emulate a WebSocket +interaction and expose the same application-level API. + +On the Servlet stack the Spring Framework provides both server (and also client) support +for the SockJS protocol. [[websocket-fallback-sockjs-overview]]