I'm exploring Spring Boot 3. I created 2 REST services where one communicates with the other. Both are using Spring-starter-web and also imported Webflux. I found we can use @HttpExchange (My previous experience is Spring Boot 2.6 and also used only RestClient). I have followed this link to try.
I have added @HttpExchange. Created HttpServiceProxyFactory bean as well. Below is my code. How to pass custom headers dynamically? Let's say I want to pass the authenticated user data in the header or some other values that are to be set dynamically.
Client
@HttpExchange("/blog")
public interface BlogClient {
@PostExchange
Mono<Course> create(@RequestBody BlogInfo blogInfo);
@GetExchange
Mono<Course> get(@PathVariable Long id);
}
Configuration
WebClient webClient(String url) {
return WebClient.builder().baseUrl(url).build();
}
@Bean
BlogClient blogClient() {
HttpServiceProxyFactory httpServiceProxyFactory = HttpServiceProxyFactory
.builder(WebClientAdapter.forClient(webClient(blogBaseURL))).build();
return httpServiceProxyFactory.createClient(BlogClient.class);
}
Update
I have figured out we can add @RequestHeader as a parameter and pass headers. Similar to reading headers. But then the parameter needs to be added in all methods of all exchange interfaces which seems too much.
@PostExchange
Mono<Course> create(@RequestBody BlogInfo blogInfo, @RequestHeader Map<String, String> headers);
@GetExchange
Mono<Course> get(@PathVariable Long id, @RequestHeader Map<String, String> headers);
If we want to set a global header whose value changes for each outgoing request, we can use the ExchangeFilterFunction. [Updated Article]
@Component
public class DynamicHeaderFilter implements ExchangeFilterFunction {
@Override
public Mono<ClientResponse> filter(ClientRequest clientRequest, ExchangeFunction nextFilter) {
// Create a new ClientRequest with the additional headers
ClientRequest modifiedRequest = ClientRequest
.from(clientRequest)
.header("X-REQUEST-TIMESTAMP", LocalDateTime.now().toString())
.build();
return nextFilter.exchange(modifiedRequest);
}
}
Next, register the DynamicHeaderFilter with the WebClient so it is invoked for each outgoing request.
@Autowired
DynamicHeaderFilter dynamicHeaderFilter;
@Bean
WebClient webClient(ObjectMapper objectMapper) {
return WebClient.builder()
...
.filter(dynamicHeaderFilter)
...
.build();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With