Search code examples
javaspringresttemplate

What is the behaviour of a RestTemplate when multiple ClientHttpRequestInterceptors are registered?


Imagine I have the following the following 2 ClientHttpRequestInterceptors:

public class RequestLoggerInterceptor implements ClientHttpRequestInterceptor {
  @Override
  public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
    log.info("HTTP request: {}", httpRequest);
    return clientHttpRequestExecution.execute(httpRequest, bytes);
  }
}
public class ResponseLoggerInterceptor implements ClientHttpRequestInterceptor {
  @Override
  public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes, ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
    ClientHttpResponse response = clientHttpRequestExecution.execute(httpRequest, bytes);
    log.info("HTTP response: {}", response);
    return response
  }
}

And I add them both to the same RestTemplate:

ClientHttpRequestInterceptor requestLogger = new RequestLoggerInterceptor();
ClientHttpRequestInterceptor responseLoggerr = new ResponseLoggerInterceptor();
RestTemplate template = new RestTemplate();
template.setInterceptors(Arrays.asList(requestLogger, responseLogger));

What will be the behaviour when a request is executed using this RestTemplate?

In both ClientHttpRequestInterceptors, the clientHttpRequestExecution.execute method is called. Does this mean that the request is executed twice?


Solution

  • From the documentation of ClientHttpRequestExecution

    Represents the context of a client-side HTTP request execution. Used to invoke the next interceptor in the interceptor chain, or - if the calling interceptor is last - execute the request itself.

    Hence the request will not execute twice. It will execute in following way,

    1. start clientHttpRequestExecution.execute
    2. call first interceptor requestLogger.intercept
    3. call back clientHttpRequestExecution.execute
    4. call second interceptor responseLogger.intercept
    5. call back clientHttpRequestExecution.execute
    6. no interceptor left, call actual ClientHttpRequest.execute

    For more details, read InterceptingClientHttpRequest InterceptingRequestExecution.execute method.