Add advice on using exchange from an ExchangeFilterFunction
Closes gh-26819
This commit is contained in:
parent
5740eaf33e
commit
d25ae4b02c
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -39,6 +39,13 @@ public interface ExchangeFilterFunction {
|
|||
* in the chain, to be invoked via
|
||||
* {@linkplain ExchangeFunction#exchange(ClientRequest) invoked} in order to
|
||||
* proceed with the exchange, or not invoked to shortcut the chain.
|
||||
*
|
||||
* <p><strong>Note:</strong> When a filter handles the response after the
|
||||
* call to {@link ExchangeFunction#exchange}, extra care must be taken to
|
||||
* always consume its content or otherwise propagate it downstream for
|
||||
* further handling, for example by the {@link WebClient}. Please, see the
|
||||
* reference documentation for more details on this.
|
||||
*
|
||||
* @param request the current request
|
||||
* @param next the next exchange function in the chain
|
||||
* @return the filtered response
|
||||
|
|
|
@ -43,6 +43,14 @@ public interface ExchangeFunction {
|
|||
|
||||
/**
|
||||
* Exchange the given request for a {@link ClientResponse} promise.
|
||||
*
|
||||
* <p><strong>Note:</strong> When a calling this method from an
|
||||
* {@link ExchangeFilterFunction} that handles the response in some way,
|
||||
* extra care must be taken to always consume its content or otherwise
|
||||
* propagate it downstream for further handling, for example by the
|
||||
* {@link WebClient}. Please, see the reference documentation for more
|
||||
* details on this.
|
||||
*
|
||||
* @param request the request to exchange
|
||||
* @return the delayed response
|
||||
*/
|
||||
|
|
|
@ -889,9 +889,8 @@ a filter for basic authentication through a static factory method:
|
|||
.build()
|
||||
----
|
||||
|
||||
You can create a new `WebClient` instance by using another as a starting point. This allows
|
||||
insert or removing filters without affecting the original `WebClient`. Below is an example
|
||||
that inserts a basic authentication filter at index 0:
|
||||
Filters can be added or removed by mutating an existing `WebClient` instance, resulting
|
||||
in a new `WebClient` instance that does not affect the original one. For example:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
|
@ -912,6 +911,53 @@ that inserts a basic authentication filter at index 0:
|
|||
.build()
|
||||
----
|
||||
|
||||
`WebClient` is a thin facade around the chain of filters followed by an
|
||||
`ExchangeFunction`. It provides a workflow to make requests, to encode to and from higher
|
||||
level objects, and it helps to ensure that response content is always consumed.
|
||||
When filters handle the response in some way, extra care must be taken to always consume
|
||||
its content or to otherwise propagate it downstream to the `WebClient` which will ensure
|
||||
the same. Below is a filter that handles the `UNAUTHORIZED` status code but ensures that
|
||||
any response content, whether expected or not, is released:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
.Java
|
||||
----
|
||||
public ExchangeFilterFunction renewTokenFilter() {
|
||||
return (request, next) -> next.exchange(request).flatMap(response -> {
|
||||
if (response.statusCode().value() == HttpStatus.UNAUTHORIZED.value()) {
|
||||
return response.releaseBody()
|
||||
.then(renewToken())
|
||||
.flatMap(token -> {
|
||||
ClientRequest newRequest = ClientRequest.from(request).build();
|
||||
return next.exchange(newRequest);
|
||||
});
|
||||
} else {
|
||||
return Mono.just(response);
|
||||
}
|
||||
});
|
||||
}
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
.Kotlin
|
||||
----
|
||||
fun renewTokenFilter(): ExchangeFilterFunction? {
|
||||
return ExchangeFilterFunction { request: ClientRequest?, next: ExchangeFunction ->
|
||||
next.exchange(request!!).flatMap { response: ClientResponse ->
|
||||
if (response.statusCode().value() == HttpStatus.UNAUTHORIZED.value()) {
|
||||
return@flatMap response.releaseBody()
|
||||
.then(renewToken())
|
||||
.flatMap { token: String? ->
|
||||
val newRequest = ClientRequest.from(request).build()
|
||||
next.exchange(newRequest)
|
||||
}
|
||||
} else {
|
||||
return@flatMap Mono.just(response)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[webflux-client-attributes]]
|
||||
== Attributes
|
||||
|
|
Loading…
Reference in New Issue