|
|
|
@ -1,11 +1,11 @@ |
|
|
|
|
[[webflux-client]] |
|
|
|
|
= WebClient |
|
|
|
|
|
|
|
|
|
Spring WebFlux includes a reactive, non-blocking `WebClient` for performing HTTP requests |
|
|
|
|
using a functional-style API that exposes Reactor `Flux` and `Mono` types, see |
|
|
|
|
<<web-reactive.adoc#webflux-reactive-libraries>>. The client relies on the same |
|
|
|
|
<<web-reactive.adoc#webflux-codecs,codecs>> that WebFlux server applications use to work |
|
|
|
|
with request and response content. |
|
|
|
|
Spring WebFlux includes a reactive, non-blocking `WebClient` for HTTP requests. The client |
|
|
|
|
has a functional, fluent API with reactive types for declarative composition, see |
|
|
|
|
<<web-reactive.adoc#webflux-reactive-libraries>>. WebFlux client and server rely on the |
|
|
|
|
same non-blocking <<web-reactive.adoc#webflux-codecs,codecs>> to encode and decode request |
|
|
|
|
and response content. |
|
|
|
|
|
|
|
|
|
Internally `WebClient` delegates to an HTTP client library. By default, it uses |
|
|
|
|
https://github.com/reactor/reactor-netty[Reactor Netty], there is built-in support for |
|
|
|
@ -22,15 +22,14 @@ The simplest way to create a `WebClient` is through one of the static factory me |
|
|
|
|
* `WebClient.create()` |
|
|
|
|
* `WebClient.create(String baseUrl)` |
|
|
|
|
|
|
|
|
|
The preceding methods use Reactor Netty `HttpClient` from `io.projectreactor.netty:reactor-netty` |
|
|
|
|
with default settings and participates in global resources for event loop threads and |
|
|
|
|
a connection pool. See <<webflux-client-builder-reactor, Reactor Netty configuration>>. |
|
|
|
|
The above methods use the Reactor Netty `HttpClient` with default settings and expect |
|
|
|
|
`io.projectreactor.netty:reactor-netty` to be on the classpath. |
|
|
|
|
|
|
|
|
|
You can use the `WebClient.Builder` for access to further options: |
|
|
|
|
You can also use `WebClient.builder()` with further options: |
|
|
|
|
|
|
|
|
|
* `uriBuilderFactory`: Customized `UriBuilderFactory` to use as a base URL. |
|
|
|
|
* `defaultHeader`: Headers for every request. |
|
|
|
|
* `defaultCookie)`: Cookies for every request. |
|
|
|
|
* `defaultCookie`: Cookies for every request. |
|
|
|
|
* `defaultRequest`: `Consumer` to customize every request. |
|
|
|
|
* `filter`: Client filter for every request. |
|
|
|
|
* `exchangeStrategies`: HTTP message reader/writer customizations. |
|
|
|
@ -78,19 +77,24 @@ modified copy without affecting the original instance, as the following example |
|
|
|
|
[[webflux-client-builder-reactor]] |
|
|
|
|
=== Reactor Netty |
|
|
|
|
|
|
|
|
|
You can customize Reactor Netty settings: |
|
|
|
|
To customize Reactor Netty settings, simple provide a pre-configured `HttpClient`: |
|
|
|
|
|
|
|
|
|
==== |
|
|
|
|
[source,java,intent=0] |
|
|
|
|
[subs="verbatim,quotes"] |
|
|
|
|
---- |
|
|
|
|
HttpClient httpClient = HttpClient.create().secure(sslSpec -> ...); |
|
|
|
|
ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient); |
|
|
|
|
|
|
|
|
|
WebClient webClient = WebClient.builder().clientConnector(connector).build(); |
|
|
|
|
WebClient webClient = WebClient.builder() |
|
|
|
|
.clientConnector(new ReactorClientHttpConnector(httpClient)) |
|
|
|
|
.build(); |
|
|
|
|
---- |
|
|
|
|
==== |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[webflux-client-builder-reactor-resources]] |
|
|
|
|
==== Resources |
|
|
|
|
|
|
|
|
|
By default, `HttpClient` participates in the global Reactor Netty resources held in |
|
|
|
|
`reactor.netty.http.HttpResources`, including event loop threads and a connection pool. |
|
|
|
|
This is the recommended mode, since fixed, shared resources are preferred for event loop |
|
|
|
@ -148,6 +152,41 @@ instances use shared resources, as the following example shows: |
|
|
|
|
==== |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[webflux-client-builder-reactor-timeout]] |
|
|
|
|
==== Timeouts |
|
|
|
|
|
|
|
|
|
To configure a connection timeout: |
|
|
|
|
|
|
|
|
|
==== |
|
|
|
|
[source,java,intent=0] |
|
|
|
|
[subs="verbatim,quotes"] |
|
|
|
|
---- |
|
|
|
|
import io.netty.channel.ChannelOption; |
|
|
|
|
|
|
|
|
|
HttpClient httpClient = HttpClient.create() |
|
|
|
|
.tcpConfiguration(client -> |
|
|
|
|
client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000)); |
|
|
|
|
---- |
|
|
|
|
==== |
|
|
|
|
|
|
|
|
|
To configure a read and/or write timeout values: |
|
|
|
|
|
|
|
|
|
==== |
|
|
|
|
[source,java,intent=0] |
|
|
|
|
[subs="verbatim,quotes"] |
|
|
|
|
---- |
|
|
|
|
import io.netty.handler.timeout.ReadTimeoutHandler; |
|
|
|
|
import io.netty.handler.timeout.WriteTimeoutHandler; |
|
|
|
|
|
|
|
|
|
HttpClient httpClient = HttpClient.create() |
|
|
|
|
.tcpConfiguration(client -> |
|
|
|
|
client.doOnConnected(conn -> conn |
|
|
|
|
.addHandlerLast(new ReadTimeoutHandler(10)) |
|
|
|
|
.addHandlerLast(new WriteTimeoutHandler(10)))); |
|
|
|
|
---- |
|
|
|
|
==== |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[webflux-client-builder-jetty]] |
|
|
|
|
=== Jetty |
|
|
|
@ -204,7 +243,7 @@ Spring-managed bean of type `JettyResourceFactory`, as the following example sho |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[webflux-client-retrieve]] |
|
|
|
|
== Using the `retrieve` Method |
|
|
|
|
== Using `retrieve()` |
|
|
|
|
|
|
|
|
|
The `retrieve()` method is the easiest way to get a response body and decode it. |
|
|
|
|
The following example shows how to do so: |
|
|
|
@ -257,7 +296,7 @@ as the following example shows: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[[webflux-client-exchange]] |
|
|
|
|
== Using the `exchange` Method |
|
|
|
|
== Using `exchange()` |
|
|
|
|
|
|
|
|
|
The `exchange()` method provides more control than the `retrieve` method. The following example is equivalent |
|
|
|
|
to `retrieve()` but also provides access to the `ClientResponse`: |
|
|
|
|