What do ExchangeFilterFunction.basicAuthentication, ofRequestProcessor, and ofResponseProcessor give you?
answer
- basicAuthentication(user,pass) -> Authorization: Basic base64
- ofRequestProcessor: Function<ClientRequest, Mono<ClientRequest>>
- ofResponseProcessor: Function<ClientResponse, Mono<ClientResponse>>
- processors call next.exchange for you
- no-arg basicAuthentication() is deprecated
basics
~10 sThey are ready-made factory methods. basicAuthentication(user, password) adds an HTTP Basic auth header. ofRequestProcessor lets you transform just the request; ofResponseProcessor lets you transform just the response — without writing the full filter method.
solid answer
~40 sThese are static factory helpers on ExchangeFilterFunction so you don't hand-write the two-argument filter method for simple cases. ExchangeFilterFunction.basicAuthentication(username, password) returns a filter that adds an Authorization: Basic header (Base64 of user:password) to every request. ExchangeFilterFunction.ofRequestProcessor(Function<ClientRequest, Mono<ClientRequest>>) builds a filter that only rewrites the outgoing request — ideal for injecting headers or tokens reactively. ExchangeFilterFunction.ofResponseProcessor(Function<ClientResponse, Mono<ClientResponse>>) builds one that only post-processes the response — useful for status normalization or error mapping. Both 'of...Processor' variants internally call next.exchange for you, so you focus on just the transform. There is also a deprecated no-arg basicAuthentication() that read credentials from request attributes; prefer the two-arg version or set the header yourself.
code
java · 16 linesWebClient client = WebClient.builder()
.baseUrl("https://api.example.com")
// fixed basic-auth on every call
.filter(ExchangeFilterFunction.basicAuthentication("svc-user", "secret"))
// async bearer token injection
.filter(ExchangeFilterFunction.ofRequestProcessor(request ->
tokenService.currentToken()
.map(t -> ClientRequest.from(request)
.header("Authorization", "Bearer " + t)
.build())))
// response-side status logging
.filter(ExchangeFilterFunction.ofResponseProcessor(response -> {
log.info("status={}", response.statusCode());
return Mono.just(response);
}))
.build();go deeper
Know basicAuthentication(user, pass) adds a Basic auth header.
Distinguish ofRequestProcessor (request-only) from ofResponseProcessor (response-only) and know they return Monos so transforms can be async.
Explain when to drop to the raw filter and the body-consumption risk in ofResponseProcessor.
Weigh fixed basicAuthentication vs. dynamic token injection and where credential lifecycle belongs.
## The problem they solve Writing `(request, next) -> { ... next.exchange(...) ... }` by hand is verbose when you only care about one side of the exchange. `ExchangeFilterFunction` exposes **static factory methods** for the common shapes. ### `ExchangeFilterFunction.basicAuthentication(String username, String password)` Returns a filter that adds an HTTP **Basic authentication** header to every request: ``` Authorization: Basic base64(username:password) ``` The encoding is Base64 of the literal string `username:password`. This is a fixed-credentials helper — the same username/password on every call. There is also a **deprecated** no-argument `basicAuthentication()` overload that pulled the username/password from *request attributes* (set via `.attribute(...)` per call). It was deprecated because setting the `Authorization` header directly (e.g., via `defaultHeaders` or `.headers(h -> h.setBasicAuth(...))`) is clearer. In interviews: know the two-arg factory; mention the no-arg one is deprecated. ### `ExchangeFilterFunction.ofRequestProcessor(Function<ClientRequest, Mono<ClientRequest>>)` Builds a filter from a function that maps the incoming `ClientRequest` to a `Mono<ClientRequest>`. The helper takes the transformed request and calls `next.exchange(...)` for you. Because the result is a `Mono`, the transform can be **asynchronous** — e.g., fetch a token reactively before attaching it: ```java ExchangeFilterFunction.ofRequestProcessor(request -> tokenService.currentToken() // Mono<String> .map(token -> ClientRequest.from(request) .header("Authorization", "Bearer " + token) .build())); ``` ### `ExchangeFilterFunction.ofResponseProcessor(Function<ClientResponse, Mono<ClientResponse>>)` Builds a filter that runs `next.exchange` and then applies your function to the resulting `ClientResponse`. Good for **response-side** cross-cutting logic: mapping 4xx/5xx into domain exceptions, extracting rate-limit headers, or logging status. ```java ExchangeFilterFunction.ofResponseProcessor(response -> { if (response.statusCode().is5xxServerError()) { // e.g., transform or log; must return a Mono<ClientResponse> } return Mono.just(response); }); ``` ## Gotchas - `ofResponseProcessor` gives you the `ClientResponse`, but **reading its body consumes it** — if you read it just to inspect, downstream code can't read it again. For error handling prefer inspecting status/headers, or use `onStatus(...)` on the request spec. - `basicAuthentication` is fixed credentials; for per-user or rotating credentials use `ofRequestProcessor` with a reactive lookup. - These helpers are just conveniences: anything they do can be done with the raw two-arg filter. ## When to use which - Static auth on every call -> `basicAuthentication(user, pass)` or `defaultHeaders`. - Dynamic/async request mutation (tokens, signing) -> `ofRequestProcessor`. - Response inspection/normalization -> `ofResponseProcessor`. - Need both sides or retry logic -> the raw `(request, next)` filter.
- Why might you use ofRequestProcessor instead of ExchangeFilterFunction.basicAuthentication?basicAuthentication uses fixed, hard-coded credentials. ofRequestProcessor accepts a Function returning Mono<ClientRequest>, so it can asynchronously fetch or refresh a token/credential per request before attaching the header.
saying these in an interview costs you the question
- Claiming basicAuthentication encrypts credentials (it only Base64-encodes them; security comes from TLS)
- Believing ofRequestProcessor can also read/transform the response (it only touches the request)
- Recommending the deprecated no-arg basicAuthentication() as the modern approach