Edit the Web chapter of the reference documentation
I edited for spelling, punctuation, grammar, usage, and corporate voice. I also added links and cross-references.
This commit is contained in:
@@ -1,30 +1,33 @@
|
||||
[[webflux-websocket]]
|
||||
= WebSockets
|
||||
[.small]#<<web.adoc#websocket,Same in Servlet stack>>#
|
||||
[.small]#<<web.adoc#websocket,Same as in the Servlet stack>>#
|
||||
|
||||
This part of the reference documentation covers support for Reactive stack, WebSocket
|
||||
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>>#
|
||||
[.small]#<<web.adoc#websocket-server,Same as in the Servlet stack>>#
|
||||
|
||||
The Spring Framework provides a WebSocket API that can be used to write client and
|
||||
server side applications that handle WebSocket messages.
|
||||
The Spring Framework provides a WebSocket API that you can use to write client- and
|
||||
server-side applications that handle WebSocket messages.
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server-handler]]
|
||||
=== Server
|
||||
[.small]#<<web.adoc#websocket-server-handler,Same in Servlet stack>>#
|
||||
[.small]#<<web.adoc#websocket-server-handler,Same as in the Servlet stack>>#
|
||||
|
||||
To create a WebSocket server, first create a `WebSocketHandler`:
|
||||
To create a WebSocket server, you can first create a `WebSocketHandler`.
|
||||
The following example shows how to do so:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -39,9 +42,11 @@ To create a WebSocket server, first create a `WebSocketHandler`:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Then map it to a URL and add a `WebSocketHandlerAdapter`:
|
||||
Then you can map it to a URL and add a `WebSocketHandlerAdapter`, as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -65,22 +70,24 @@ Then map it to a URL and add a `WebSocketHandlerAdapter`:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[webflux-websockethandler]]
|
||||
=== WebSocketHandler
|
||||
=== Using `WebSocketHandler`
|
||||
|
||||
The `handle` method of `WebSocketHandler` takes `WebSocketSession` and returns `Mono<Void>`
|
||||
to indicate when application handling of the session is complete. The session is handled
|
||||
through two streams, one for inbound and one for outbound messages:
|
||||
through two streams, one for inbound and one for outbound messages. The following table
|
||||
describes the two methods that handle the streams:
|
||||
|
||||
[options="header"]
|
||||
|===
|
||||
| WebSocketSession method | Description
|
||||
| `WebSocketSession` method | Description
|
||||
|
||||
| `Flux<WebSocketMessage> receive()`
|
||||
| Provides access to the inbound message stream, and completes when the connection is closed.
|
||||
| Provides access to the inbound message stream and completes when the connection is closed.
|
||||
|
||||
| `Mono<Void> send(Publisher<WebSocketMessage>)`
|
||||
| Takes a source for outgoing messages, writes the messages, and returns a `Mono<Void>` that
|
||||
@@ -88,21 +95,23 @@ through two streams, one for inbound and one for outbound messages:
|
||||
|
||||
|===
|
||||
|
||||
A `WebSocketHandler` must compose the inbound and outbound streams into a unified flow, and
|
||||
A `WebSocketHandler` must compose the inbound and outbound streams into a unified flow and
|
||||
return a `Mono<Void>` that reflects the completion of that flow. Depending on application
|
||||
requirements, the unified flow completes when:
|
||||
|
||||
* Either inbound or outbound message streams complete.
|
||||
* Inbound stream completes (i.e. connection closed), while outbound is infinite.
|
||||
* At a chosen point through the `close` method of `WebSocketSession`.
|
||||
* Either the inbound or the outbound message stream completes.
|
||||
* The inbound stream completes (that is, the connection closed), while the outbound stream is infinite.
|
||||
* At a chosen point, through the `close` method of `WebSocketSession`.
|
||||
|
||||
When inbound and outbound message streams are composed together, there is no need to
|
||||
check if the connection is open, since Reactive Streams signals will terminate activity.
|
||||
The inbound stream receives a completion/error signal, and the outbound stream receives
|
||||
check if the connection is open, since Reactive Streams signals terminate activity.
|
||||
The inbound stream receives a completion or error signal, and the outbound stream
|
||||
receives a cancellation signal.
|
||||
|
||||
The most basic implementation of a handler is one that handles the inbound stream:
|
||||
The most basic implementation of a handler is one that handles the inbound stream. The
|
||||
following example shows such an implementation:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -121,21 +130,20 @@ class ExampleHandler implements WebSocketHandler {
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Access stream of inbound messages.
|
||||
<1> Access the stream of inbound messages.
|
||||
<2> Do something with each message.
|
||||
<3> Perform nested async operation using message content.
|
||||
<4> Return `Mono<Void>` that completes when receiving completes.
|
||||
|
||||
[TIP]
|
||||
<3> Perform nested asynchronous operations that use the message content.
|
||||
<4> Return a `Mono<Void>` that completes when receiving completes.
|
||||
====
|
||||
For nested, asynchronous operations, you may need to call `message.retain()` on underlying
|
||||
servers that use pooled data buffers (e.g. Netty), or otherwise the data buffer may be
|
||||
released before you've had a chance to read the data. For more background see
|
||||
|
||||
TIP: For nested, asynchronous operations, you may need to call `message.retain()` on underlying
|
||||
servers that use pooled data buffers (for example, Netty). Otherwise, the data buffer may be
|
||||
released before you have had a chance to read the data. For more background, see
|
||||
<<core.adoc#databuffers,Data Buffers and Codecs>>.
|
||||
|
||||
The following implementation combines the inbound and outbound streams:
|
||||
|
||||
====
|
||||
|
||||
The below implementation combines the inbound with the outbound streams:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -157,12 +165,15 @@ class ExampleHandler implements WebSocketHandler {
|
||||
}
|
||||
}
|
||||
----
|
||||
<1> Handle inbound message stream.
|
||||
<2> Create outbound message, producing a combined flow.
|
||||
<3> Return `Mono<Void>` that doesn't complete while we continue to receive.
|
||||
<1> Handle the inbound message stream.
|
||||
<2> Create the outbound message, producing a combined flow.
|
||||
<3> Return a `Mono<Void>` that does not complete while we continue to receive.
|
||||
====
|
||||
|
||||
Inbound and outbound streams can be independent, and joined only for completion:
|
||||
Inbound and outbound streams can be independent and be joined only for completion,
|
||||
as the following example shows:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -189,17 +200,18 @@ class ExampleHandler implements WebSocketHandler {
|
||||
----
|
||||
<1> Handle inbound message stream.
|
||||
<2> Send outgoing messages.
|
||||
<3> Join the streams and return `Mono<Void>` that completes when _either_ stream ends.
|
||||
<3> Join the streams and return a `Mono<Void>` that completes when either stream ends.
|
||||
====
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server-handshake]]
|
||||
=== Handshake
|
||||
[.small]#<<web.adoc#websocket-server-handshake,Same in Servlet stack>>#
|
||||
[.small]#<<web.adoc#websocket-server-handshake,Same as in the Servlet stack>>#
|
||||
|
||||
`WebSocketHandlerAdapter` delegates to a `WebSocketService`. By default that's an instance
|
||||
`WebSocketHandlerAdapter` delegates to a `WebSocketService`. By default, that is an instance
|
||||
of `HandshakeWebSocketService`, which performs basic checks on the WebSocket request and
|
||||
then uses `RequestUpgradeStrategy` for the server in use. Currently there is built-in
|
||||
then uses `RequestUpgradeStrategy` for the server in use. Currently, there is built-in
|
||||
support for Reactor Netty, Tomcat, Jetty, and Undertow.
|
||||
|
||||
`HandshakeWebSocketService` exposes a `sessionAttributePredicate` property that allows
|
||||
@@ -208,15 +220,15 @@ into the attributes of the `WebSocketSession`.
|
||||
|
||||
|
||||
|
||||
|
||||
[[webflux-websocket-server-config]]
|
||||
=== Server config
|
||||
[.small]#<<web.adoc#websocket-server-runtime-configuration,Same in Servlet stack>>#
|
||||
=== Server Configation
|
||||
[.small]#<<web.adoc#websocket-server-runtime-configuration,Same as in the Servlet stack>>#
|
||||
|
||||
The `RequestUpgradeStrategy` for each server exposes WebSocket-related configuration
|
||||
options available for the underlying WebSocket engine. Below is an example of setting
|
||||
options available for the underlying WebSocket engine. The following example sets
|
||||
WebSocket options when running on Tomcat:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -236,21 +248,22 @@ WebSocket options when running on Tomcat:
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
Check the upgrade strategy for your server to see what options are available. Currently
|
||||
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>>#
|
||||
[.small]#<<web.adoc#websocket-server-allowed-origins,Same as in the 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
|
||||
`CorsConfiguraiton` with allowed origins, headers, and other details. If you cannot 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
|
||||
specify CORS settings by URL pattern. If both are specified, they are combined by using the
|
||||
`combine` method on `CorsConfiguration`.
|
||||
|
||||
|
||||
@@ -259,18 +272,16 @@ specify CORS settings by URL pattern. If both are specified they're combined via
|
||||
=== Client
|
||||
|
||||
Spring WebFlux provides a `WebSocketClient` abstraction with implementations for
|
||||
Reactor Netty, Tomcat, Jetty, Undertow, and standard Java (i.e. JSR-356).
|
||||
Reactor Netty, Tomcat, Jetty, Undertow, and standard Java (that is, 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
|
||||
NOTE: The Tomcat client is effectively an extension of the standard Java one with some extra
|
||||
functionality in the `WebSocketSession` handling to take advantage of the 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`
|
||||
To start a WebSocket session, you can create an instance of the client and use its `execute`
|
||||
methods:
|
||||
|
||||
====
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@@ -282,7 +293,8 @@ client.execute(url, session ->
|
||||
.doOnNext(System.out::println)
|
||||
.then());
|
||||
----
|
||||
====
|
||||
|
||||
Some clients, e.g. Jetty, implement `Lifecycle` and need to be started in stopped
|
||||
Some clients, such as Jetty, implement `Lifecycle` and need to be stopped and started
|
||||
before you can use them. All clients have constructor options related to configuration
|
||||
of the underlying WebSocket client.
|
||||
|
||||
Reference in New Issue
Block a user