Careeroza
Headers and Request Interceptors
Static Headers on a Method
@FeignClient(name = "payment-service", path = "/api/payments")
public interface PaymentClient {
@PostMapping(headers = "X-Client=order-service")
PaymentResponse charge(@RequestHeader("Idempotency-Key") String idempotencyKey,
@RequestBody ChargeRequest request);
}The Idempotency-Key (for example the order ID) lets payment-service detect a repeated charge request and return the first result instead of charging twice. More on idempotency in the advance level.
Forward the Token and Correlation ID Automatically
A RequestInterceptor runs before every Feign call. This one copies the incoming Authorization and X-Correlation-Id headers to outgoing calls, so the user identity and the trace follow the request through all services:
@Configuration
class FeignHeadersConfig {
private static final List<String> FORWARDED = List.of("Authorization", "X-Correlation-Id");
@Bean
RequestInterceptor forwardHeadersInterceptor() {
return template -> {
if (RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes attrs) {
HttpServletRequest incoming = attrs.getRequest();
for (String name : FORWARDED) {
String value = incoming.getHeader(name);
if (value != null) {
template.header(name, value);
}
}
}
};
}
}gateway --(Authorization, X-Correlation-Id: 3f2b...)--> order-service order-service --Feign + interceptor--> product-service (same two headers) order-service --Feign + interceptor--> payment-service (same two headers)
Note: RequestContextHolder is bound to the request thread. If you call Feign from @Async methods or another thread pool, the attributes are empty; pass the values explicitly there.