2

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);
Coder
  • 6,948
  • 13
  • 56
  • 86

1 Answers1

0

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();
}
Lokesh Gupta
  • 463
  • 5
  • 8
  • But how do you set the values dynamically? This is during initialization. The username and password or token or some value I need to generate dynamically and not during initialization. – Coder Sep 02 '23 at 12:47