@@ -831,7 +831,7 @@ inline-style, through the built-in `BodyInserters`, as the following example sho
831
831
832
832
833
833
[[webflux-client-filter]]
834
- == Client Filters
834
+ == Filters
835
835
836
836
You can register a client filter (`ExchangeFilterFunction`) through the `WebClient.Builder`
837
837
in order to intercept and modify requests, as the following example shows:
@@ -887,9 +887,36 @@ a filter for basic authentication through a static factory method:
887
887
.build()
888
888
----
889
889
890
- Filters apply globally to every request. To change a filter's behavior for a specific
891
- request, you can add request attributes to the `ClientRequest` that can then be accessed
892
- by all filters in the chain, as the following example shows:
890
+ You can create a new `WebClient` instance by using another as a starting point. This allows
891
+ insert or removing filters without affecting the original `WebClient`. Below is an example
892
+ that inserts a basic authentication filter at index 0:
893
+
894
+ [source,java,indent=0,subs="verbatim,quotes",role="primary"]
895
+ .Java
896
+ ----
897
+ import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
898
+
899
+ WebClient client = webClient.mutate()
900
+ .filters(filterList -> {
901
+ filterList.add(0, basicAuthentication("user", "password"));
902
+ })
903
+ .build();
904
+ ----
905
+ [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
906
+ .Kotlin
907
+ ----
908
+ val client = webClient.mutate()
909
+ .filters { it.add(0, basicAuthentication("user", "password")) }
910
+ .build()
911
+ ----
912
+
913
+
914
+ [[webflux-client-attributes]]
915
+ == Attributes
916
+
917
+ You can add attributes to a request. This is convenient if you want to pass information
918
+ through the filter chain and influence the behavior of filters for a given request.
919
+ For example:
893
920
894
921
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
895
922
.Java
@@ -912,40 +939,56 @@ by all filters in the chain, as the following example shows:
912
939
.Kotlin
913
940
----
914
941
val client = WebClient.builder()
915
- .filter { request, _ ->
916
- val usr = request.attributes()["myAttribute"];
917
- // ...
918
- }.build()
942
+ .filter { request, _ ->
943
+ val usr = request.attributes()["myAttribute"];
944
+ // ...
945
+ }
946
+ .build()
919
947
920
948
client.get().uri("https://example.org/")
921
949
.attribute("myAttribute", "...")
922
950
.retrieve()
923
951
.awaitBody<Unit>()
924
952
----
925
953
926
- You can also replicate an existing `WebClient`, insert new filters, or remove already
927
- registered filters. The following example, inserts a basic authentication filter at
928
- index 0:
954
+
955
+ [[webflux-client-context]]
956
+ == Context
957
+
958
+ <<webflux-client-attributes>> provide a convenient way to pass information to the filter
959
+ chain but they only influence the current request. If you want to pass information that
960
+ propagates to additional requests that are nested, e.g. via `flatMap`, or executed after,
961
+ e.g. via `concatMap`, then you'll need to use the Reactor `Context`.
962
+
963
+ `WebClient` exposes a method to populate the Reactor `Context` for a given request.
964
+ This information is available to filters for the current request and it also propagates
965
+ to subsequent requests or other reactive clients participating in the downstream
966
+ processing chain. For example:
929
967
930
968
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
931
969
.Java
932
970
----
933
- import static org.springframework.web.reactive.function.client.ExchangeFilterFunctions.basicAuthentication;
934
-
935
- WebClient client = webClient.mutate()
936
- .filters(filterList -> {
937
- filterList.add(0, basicAuthentication("user", "password"));
938
- } )
971
+ WebClient client = WebClient.builder()
972
+ .filter((request, next) ->
973
+ Mono.deferContextual(contextView -> {
974
+ String value = contextView.get("foo");
975
+ // ...
976
+ }) )
939
977
.build();
940
- ----
941
- [source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
942
- .Kotlin
943
- ----
944
- val client = webClient.mutate()
945
- .filters { it.add(0, basicAuthentication("user", "password")) }
946
- .build()
978
+
979
+ client.get().uri("https://example.org/")
980
+ .context(context -> context.put("foo", ...))
981
+ .retrieve()
982
+ .bodyToMono(String.class)
983
+ .flatMap(body -> {
984
+ // perform nested request (context propagates automatically)...
985
+ });
947
986
----
948
987
988
+ Note that you can also specify how to populate the context through the `defaultRequest`
989
+ method at the level of the `WebClient.Builder` and that applies to all requests.
990
+ This could be used for to example to pass information from `ThreadLocal` storage onto
991
+ a Reactor processing chain in a Spring MVC application.
949
992
950
993
951
994
[[webflux-client-synchronous]]
0 commit comments