In order to log all HTTP requests and response of Apache we need to implement HttpRequestInterceptor
and HttpResponseInterceptor
interfaces and then register them in the HTTP client.
Actually we just need to implement one method for each - process(..)
. That’s the plan, let’s do it.
LoggingRequestInterceptor
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.protocol.HttpContext;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.stream.Collectors;
public class LoggingRequestInterceptor implements HttpRequestInterceptor {
@Override
public void process(HttpRequest request, HttpContext context) throws IOException {
String message = buildRequestEntry(request, context)
+ buildHeadersEntry(request.getAllHeaders())
+ buildEntityEntry(request);
MyLogger.info(message);
}
private String buildRequestEntry(HttpRequest request, HttpContext context) {
return "\nRequest - "
+ request.getRequestLine().getMethod + " "
+ context.getAttribute("http.target_host")
+ request.getRequestLine().getUri();
}
private String buildHeadersEntry(Header[] headers) {
return "\nHeaders: ["
+ Arrays.asList(headers).stream()
.map(header -> header.getName() + ": " + header.getValue())
.collect(Collectors.joining(", "))
+ "]";
}
private String buildEntityEntry(HttpRequest request) throws IOException {
if (request instanceof HttpEntityEnclosingRequest) {
HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity();
ByteArrayOutputStream bs = new ByteArrayOutputStream();
entity.writeTo(bs);
return "\nPayload:\n" + new String(bs.toByteArray());
}
}
}
LoggingResponseInterceptor
Similarly for the HttpResponseInterceptor implementation
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.entity.StringEntity;
import org.apache.http.protocol.HttpContext;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.stream.Collectors;
public class LoggingResponseInterceptor implements HttpResponseInterceptor {
@Override
public void process(HttpResponse response, HttpContext context) throws HttpException, IOException {
String message = buildStatusEntry(response)
+ buildHeadersEntry(response.getAllHeaders())
+ buildEntityEntry(response);
MyLogger.info(message);
}
private String buildStatusEntry(HttpResponse response) {
return "\nResponse - "
+ response.getStatusLine().getStatusCode() + " "
+ response.getStatusLine().getReasonPhrase();
}
private String buildHeadersEntry(Header[] headers) {
return "\nHeaders: ["
+ Arrays.asList(headers).stream()
.map(header -> header.getName() + ": " + header.getValue())
.collect(Collectors.joining(", "))
+ "]";
}
private void buildEntityEntry() throws IOException {
BufferedReader buffer = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String payload = buffer.lines().collect(Collectors.joining("\n"));
response.setEntity(new StringEntity(payload));
return "\nPayload: \n" + payload;
}
}
Here we had to do a little trick - we re-set response’s entity after reading. You can read it only once so if you don’t do that the reasponse will be unusable.
Register Logging Interceptors
Finally we register the logging interceptors in the Apache HTTP client.
CloseableHttpClient httpClient = HttpClientBuilder.create()
.addInterceptorFirst(new LoggingRequestInterceptor())
.addInterceptorLast(new LoggingResponseInterceptor())
// More configuration if needed here
.build();
That’s it.
Now you can use the httpClient as an http engine for RESTEasy or RestTemplate clients.
RESTEasy Proxy Configuration Example
UserService userServiceClient = new ResteasyClientBuilder()
.httpEngine(new ApacheHttpClient43Engine(httpClient, true))
.build()
.target(serviceBaseUrl)
.proxy(UserService.class);
You may also find these posts interesting: