[[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.
