Add WebSocket chapter to WebFlux section
Issue: SPR-15700
This commit is contained in:
parent
0dd31b834e
commit
536e72c8df
|
|
@ -171,7 +171,9 @@ public abstract class AbstractWebSocketIntegrationTests {
|
|||
|
||||
@Bean
|
||||
public WebSocketService webSocketService() {
|
||||
return new HandshakeWebSocketService(getUpgradeStrategy());
|
||||
TomcatRequestUpgradeStrategy strategy = new TomcatRequestUpgradeStrategy();
|
||||
strategy.setMaxSessionIdleTimeout(0L);
|
||||
return new HandshakeWebSocketService(strategy);
|
||||
}
|
||||
|
||||
protected abstract RequestUpgradeStrategy getUpgradeStrategy();
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ include::web/webflux.adoc[leveloffset=+1]
|
|||
|
||||
include::web/webflux-webclient.adoc[leveloffset=+1]
|
||||
|
||||
include::web/webflux-websocket.adoc[leveloffset=+1]
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,167 @@
|
|||
[[webflux-websocket]]
|
||||
= WebSockets
|
||||
[.small]#<<web.adoc#websocket,Same in Servlet stack>>#
|
||||
|
||||
This part of the reference documentation covers support for Reactive stack, WebSocket
|
||||
messaging.
|
||||
|
||||
|
||||
include::websocket-intro.adoc[leveloffset=+1]
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server]]
|
||||
== WebSocket API
|
||||
[.small]#<<web.adoc#websocket-server,Same in Servlet stack>>#
|
||||
|
||||
The Spring Framework provides a WebSocket API that can be used to write client and
|
||||
server side applications that handle WebSocket messages.
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server-handler]]
|
||||
=== WebSocketHandler
|
||||
[.small]#<<web.adoc#websocket-server-handler,Same in Servlet stack>>#
|
||||
|
||||
Creating a WebSocket server is as simple as implementing `WebSocketHandler`:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
import org.springframework.web.reactive.socket.WebSocketHandler;
|
||||
import org.springframework.web.reactive.socket.WebSocketSession;
|
||||
|
||||
public class MyWebSocketHandler implements WebSocketHandler {
|
||||
|
||||
@Override
|
||||
public Mono<Void> handle(WebSocketSession session) {
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
Spring WebFlux provides a `WebSocketHandlerAdapter` that can adapt WebSocket
|
||||
requests and use the above handler to handle the resulting WebSocket session. After the
|
||||
adapter is registered as a bean, you can map requests to your handler, for example using
|
||||
`SimpleUrlHandlerMapping`. This is shown below:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@Configuration
|
||||
static class WebConfig {
|
||||
|
||||
@Bean
|
||||
public HandlerMapping handlerMapping() {
|
||||
Map<String, WebSocketHandler> map = new HashMap<>();
|
||||
map.put("/path", new MyWebSocketHandler());
|
||||
|
||||
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
|
||||
mapping.setUrlMap(map);
|
||||
mapping.setOrder(-1); // before annotated controllers
|
||||
return mapping;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSocketHandlerAdapter handlerAdapter() {
|
||||
return new WebSocketHandlerAdapter();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server-handshake]]
|
||||
=== WebSocket Handshake
|
||||
[.small]#<<web.adoc#websocket-server-handshake,Same in Servlet stack>>#
|
||||
|
||||
`WebSocketHandlerAdapter` does not perform WebSocket handshakes itself. Instead it
|
||||
delegates to an instance of `WebSocketService`. The default `WebSocketService`
|
||||
implementation is `HandshakeWebSocketService`.
|
||||
|
||||
The `HandshakeWebSocketService` performs basic checks on the WebSocket request and
|
||||
delegates to a server-specific `RequestUpgradeStrategy`. At present upgrade strategies
|
||||
exist for Reactor Netty, Tomcat, Jetty, and Undertow.
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server-config]]
|
||||
=== Server config
|
||||
[.small]#<<web.adoc#websocket-server-runtime-configuration,Same in Servlet stack>>#
|
||||
|
||||
The `RequestUpgradeStrategy` for each server exposes the WebSocket-related configuration
|
||||
options available for the underlying WebSocket engine. Below is an example of setting
|
||||
WebSocket options when running on Tomcat:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@Configuration
|
||||
static class WebConfig {
|
||||
|
||||
@Bean
|
||||
public WebSocketHandlerAdapter handlerAdapter() {
|
||||
return new WebSocketHandlerAdapter(webSocketService());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebSocketService webSocketService() {
|
||||
TomcatRequestUpgradeStrategy strategy = new TomcatRequestUpgradeStrategy();
|
||||
strategy.setMaxSessionIdleTimeout(0L);
|
||||
return new HandshakeWebSocketService(strategy);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
Check the upgrade strategy for your server to see what options are available. Currently
|
||||
only Tomcat and Jetty expose such options.
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server-cors]]
|
||||
=== CORS
|
||||
[.small]#<<web.adoc#websocket-server-allowed-origins,Same in Servlet stack>>#
|
||||
|
||||
The easiest way to configure CORS and restrict access to a WebSocket endpoint is to
|
||||
have your `WebSocketHandler` implement `CorsConfigurationSource` and return a
|
||||
`CorsConfiguraiton` with allowed origins, headers, etc. If for any reason you can't do
|
||||
that, you can also set the `corsConfigurations` property on the `SimpleUrlHandler` to
|
||||
specify CORS settings by URL pattern. If both are specified they're combined via the
|
||||
`combine` method on `CorsConfiguration`.
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-client]]
|
||||
== WebSocketClient
|
||||
|
||||
Spring WebFlux provides a `WebSocketClient` abstraction with implementations for
|
||||
Reactor Netty, Tomcat, Jetty, Undertow, and standard Java (i.e. JSR-356).
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The Tomcat client is effectively an extension of the standard Java one with some extra
|
||||
functionality in the `WebSocketSession` handling taking advantage of Tomcat specific
|
||||
API to suspend receiving messages for back pressure.
|
||||
====
|
||||
|
||||
To start a WebSocket session, create an instance of the client and use its `execute`
|
||||
methods:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
WebSocketClient client = new ReactorNettyWebSocketClient();
|
||||
|
||||
URI url = new URI("ws://localhost:8080/path");
|
||||
client.execute(url, session ->
|
||||
session.receive()
|
||||
.doOnNext(System.out::println)
|
||||
.then());
|
||||
----
|
||||
|
||||
Some clients, e.g. Jetty, implement `Lifecycle` and need to be started in stopped
|
||||
before you can use them. All clients have constructor options related to configuration
|
||||
of the underlying WebSocket client.
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
[[websocket]]
|
||||
= WebSockets
|
||||
:doc-spring-security: {doc-root}/spring-security/site/docs/current/reference
|
||||
[.small]#<<web-reactive.adoc#webflux-websocket,Same in Spring WebFlux>>#
|
||||
|
||||
This part of the reference documentation covers support for Servlet stack, WebSocket
|
||||
messaging that includes raw WebSocket interactions, WebSocket emulation via SockJS, and
|
||||
|
|
@ -10,32 +11,19 @@ pub-sub messaging via STOMP as a sub-protocol over WebSocket.
|
|||
include::websocket-intro.adoc[leveloffset=+1]
|
||||
|
||||
|
||||
|
||||
[[websocket-server]]
|
||||
== WebSocket API
|
||||
[.small]#<<web-reactive.adoc#webflux-websocket-server,Same in Spring WebFlux>>#
|
||||
|
||||
The Spring Framework provides a WebSocket API designed to adapt to various WebSocket engines.
|
||||
Currently the list includes WebSocket runtimes such as Tomcat 7.0.47+, Jetty 9.1+,
|
||||
GlassFish 4.1+, WebLogic 12.1.3+, and Undertow 1.0+ (and WildFly 8.0+). Additional support
|
||||
may be added as more WebSocket runtimes become available.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
As explained in the <<websocket-intro-sub-protocol,introduction>>, direct use of a
|
||||
WebSocket API is too low level for applications -- until assumptions are made about the
|
||||
format of a message there is little a framework can do to interpret messages or route
|
||||
them via annotations. This is why applications should consider using a sub-protocol
|
||||
and Spring's <<websocket-stomp>> support.
|
||||
|
||||
When using a higher level protocol, the details of the WebSocket API become less
|
||||
relevant, much like the details of TCP communication are not exposed to applications
|
||||
when using HTTP. Nevertheless this section covers the details of using WebSocket
|
||||
directly.
|
||||
====
|
||||
The Spring Framework provides a WebSocket API that can be used to write client and
|
||||
server side applications that handle WebSocket messages.
|
||||
|
||||
|
||||
|
||||
[[websocket-server-handler]]
|
||||
=== WebSocketHandler
|
||||
[.small]#<<web-reactive.adoc#webflux-websocket-server-handler,Same in Spring WebFlux>>#
|
||||
|
||||
Creating a WebSocket server is as simple as implementing `WebSocketHandler` or more
|
||||
likely extending either `TextWebSocketHandler` or `BinaryWebSocketHandler`:
|
||||
|
|
@ -117,6 +105,7 @@ into other HTTP serving environments with the help of
|
|||
|
||||
[[websocket-server-handshake]]
|
||||
=== WebSocket Handshake
|
||||
[.small]#<<web-reactive.adoc#webflux-websocket-server-handshake,Same in Spring WebFlux>>#
|
||||
|
||||
The easiest way to customize the initial HTTP WebSocket handshake request is through
|
||||
a `HandshakeInterceptor`, which exposes "before" and "after" the handshake methods.
|
||||
|
|
@ -204,16 +193,19 @@ Neither of these mechanism makes it possible to use a single "front controller"
|
|||
for all HTTP processing -- including WebSocket handshake and all other HTTP
|
||||
requests -- such as Spring MVC's `DispatcherServlet`.
|
||||
|
||||
This is a significant limitation of JSR-356 that Spring's WebSocket support
|
||||
addresses by providing a server-specific `RequestUpgradeStrategy` even when
|
||||
running in a JSR-356 runtime.
|
||||
This is a significant limitation of JSR-356 that Spring's WebSocket support addresses
|
||||
server-specific ``RequestUpgradeStrategy``'s even when running in a JSR-356 runtime.
|
||||
Such strategies currently exist for Tomcat, Jetty, GlassFish, WebLogic, WebSphere, and
|
||||
Undertow (and WildFly).
|
||||
|
||||
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
A request to overcome the above limitation in the Java WebSocket API has been
|
||||
created and can be followed at
|
||||
https://java.net/jira/browse/WEBSOCKET_SPEC-211[WEBSOCKET_SPEC-211].
|
||||
Also note that Tomcat and Jetty already provide native API alternatives that
|
||||
Tomcat, Jetty, and WebSphere provide their own API alternatives that
|
||||
makes it easy to overcome the limitation. We are hopeful that more servers
|
||||
will follow their example regardless of when it is addressed in the
|
||||
Java WebSocket API.
|
||||
|
|
@ -266,6 +258,7 @@ Java initialization API, if required:
|
|||
|
||||
[[websocket-server-runtime-configuration]]
|
||||
=== Server config
|
||||
[.small]#<<web-reactive.adoc#webflux-websocket-server-config,Same in Spring WebFlux>>#
|
||||
|
||||
Each underlying WebSocket engine exposes configuration properties that control
|
||||
runtime characteristics such as the size of message buffer sizes, idle timeout,
|
||||
|
|
@ -394,6 +387,7 @@ or WebSocket XML namespace:
|
|||
|
||||
[[websocket-server-allowed-origins]]
|
||||
=== Allowed origins
|
||||
[.small]#<<web-reactive.adoc#webflux-websocket-server-cors,Same in Spring WebFlux>>#
|
||||
|
||||
As of Spring Framework 4.1.5, the default behavior for WebSocket and SockJS is to accept
|
||||
only _same origin_ requests. It is also possible to allow _all_ or a specified list of origins.
|
||||
|
|
|
|||
Loading…
Reference in New Issue