Skip to content

Commit

Permalink
Added 'logbook.httpclient.decompress-response' flag
Browse files Browse the repository at this point in the history
  • Loading branch information
lcostelaPyxis committed Jul 21, 2023
1 parent 8ebe0c3 commit 0f44cb4
Show file tree
Hide file tree
Showing 11 changed files with 51 additions and 38 deletions.
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -934,21 +934,22 @@ MyClient(RestTemplateBuilder builder, LogbookClientHttpRequestInterceptor interc

The following tables show the available configuration:

| Configuration | Description | Default |
|------------------------------------|------------------------------------------------------------------------------------------------------|-------------------------------|
| `logbook.include` | Include only certain URLs (if defined) | `[]` |
| `logbook.exclude` | Exclude certain URLs (overrides `logbook.include`) | `[]` |
| `logbook.filter.enabled` | Enable the [`LogbookFilter`](#servlet) | `true` |
| `logbook.filter.form-request-mode` | Determines how [form requests](#form-requests) are handled | `body` |
| `logbook.secure-filter.enabled` | Enable the [`SecureLogbookFilter`](#servlet) | `true` |
| `logbook.format.style` | [Formatting style](#formatting) (`http`, `json`, `curl` or `splunk`) | `json` |
| `logbook.strategy` | [Strategy](#strategy) (`default`, `status-at-least`, `body-only-if-status-at-least`, `without-body`) | `default` |
| `logbook.minimum-status` | Minimum status to enable logging (`status-at-least` and `body-only-if-status-at-least`) | `400` |
| `logbook.obfuscate.headers` | List of header names that need obfuscation | `[Authorization]` |
| `logbook.obfuscate.paths` | List of paths that need obfuscation. Check [Filtering](#filtering) for syntax. | `[]` |
| `logbook.obfuscate.parameters` | List of parameter names that need obfuscation | `[access_token]` |
| `logbook.write.chunk-size` | Splits log lines into smaller chunks of size up-to `chunk-size`. | `0` (disabled) |
| `logbook.write.max-body-size` | Truncates the body up to `max-body-size` and appends `...`. | `-1` (disabled) |
| Configuration | Description | Default |
|------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------|
| `logbook.include` | Include only certain URLs (if defined) | `[]` |
| `logbook.exclude` | Exclude certain URLs (overrides `logbook.include`) | `[]` |
| `logbook.filter.enabled` | Enable the [`LogbookFilter`](#servlet) | `true` |
| `logbook.filter.form-request-mode` | Determines how [form requests](#form-requests) are handled | `body` |
| `logbook.secure-filter.enabled` | Enable the [`SecureLogbookFilter`](#servlet) | `true` |
| `logbook.format.style` | [Formatting style](#formatting) (`http`, `json`, `curl` or `splunk`) | `json` |
| `logbook.strategy` | [Strategy](#strategy) (`default`, `status-at-least`, `body-only-if-status-at-least`, `without-body`) | `default` |
| `logbook.minimum-status` | Minimum status to enable logging (`status-at-least` and `body-only-if-status-at-least`) | `400` |
| `logbook.obfuscate.headers` | List of header names that need obfuscation | `[Authorization]` |
| `logbook.obfuscate.paths` | List of paths that need obfuscation. Check [Filtering](#filtering) for syntax. | `[]` |
| `logbook.obfuscate.parameters` | List of parameter names that need obfuscation | `[access_token]` |
| `logbook.write.chunk-size` | Splits log lines into smaller chunks of size up-to `chunk-size`. | `0` (disabled) |
| `logbook.write.max-body-size` | Truncates the body up to `max-body-size` and appends `...`. | `-1` (disabled) |
| `logbook.httpclient.decompress-response` | Enables/disables additional decompression process for HttpClient with gzip encoded body (to logging purposes only). This means extra decompression and possible performance impact. | `false` (disabled) |

##### Example configuration

Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
package org.zalando.logbook.httpclient;

import static org.apiguardian.api.API.Status.EXPERIMENTAL;

import java.io.IOException;
import java.io.UncheckedIOException;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.nio.protocol.HttpAsyncResponseConsumer;
import org.apache.http.protocol.HttpContext;
import org.apiguardian.api.API;
import org.zalando.logbook.Logbook.ResponseProcessingStage;

import java.io.IOException;
import java.io.UncheckedIOException;

import static org.apiguardian.api.API.Status.EXPERIMENTAL;

@API(status = EXPERIMENTAL)
public final class LogbookHttpAsyncResponseConsumer<T> extends ForwardingHttpAsyncResponseConsumer<T> {

private final HttpAsyncResponseConsumer<T> consumer;
private final boolean decompressResponse;
private HttpResponse response;

public LogbookHttpAsyncResponseConsumer(final HttpAsyncResponseConsumer<T> consumer) {
public LogbookHttpAsyncResponseConsumer(HttpAsyncResponseConsumer<T> consumer, boolean decompressResponse) {
this.consumer = consumer;
this.decompressResponse = decompressResponse;
}

@Override
Expand All @@ -38,7 +39,7 @@ public void responseCompleted(final HttpContext context) {
final ResponseProcessingStage stage = find(context);

try {
stage.process(new RemoteResponse(response)).write();
stage.process(new RemoteResponse(response, decompressResponse)).write();
} catch (final IOException e) {
throw new UncheckedIOException(e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,34 @@
package org.zalando.logbook.httpclient;

import static org.apiguardian.api.API.Status.STABLE;

import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.nio.client.HttpAsyncClient;
import org.apache.http.protocol.HttpContext;
import org.apiguardian.api.API;
import org.zalando.logbook.Logbook.ResponseProcessingStage;

import java.io.IOException;

import static org.apiguardian.api.API.Status.STABLE;

/**
* A response interceptor for synchronous responses. For {@link HttpAsyncClient} support, please use
* {@link LogbookHttpAsyncResponseConsumer} instead.
* A response interceptor for synchronous responses. For {@link HttpAsyncClient} support, please use {@link LogbookHttpAsyncResponseConsumer} instead.
*
* @see LogbookHttpRequestInterceptor
* @see LogbookHttpAsyncResponseConsumer
*/
@API(status = STABLE)
public final class LogbookHttpResponseInterceptor implements HttpResponseInterceptor {

private final boolean decompressResponse;

public LogbookHttpResponseInterceptor(boolean decompressResponse) {
this.decompressResponse = decompressResponse;
}

@Override
public void process(final HttpResponse original, final HttpContext context) throws IOException {
final ResponseProcessingStage stage = find(context);
stage.process(new RemoteResponse(original)).write();
stage.process(new RemoteResponse(original, decompressResponse)).write();
}

private ResponseProcessingStage find(final HttpContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ final class RemoteResponse implements org.zalando.logbook.HttpResponse {

private final AtomicReference<State> state = new AtomicReference<>(new Unbuffered());
private final HttpResponse response;
private final boolean decompressResponse;

private interface State {

Expand Down Expand Up @@ -198,7 +199,7 @@ private static byte[] getDecompressedBytes(byte[] body) throws IOException {
@Override
public byte[] getBody() throws IOException {
byte[] body = state.updateAndGet(throwingUnaryOperator(s -> s.buffer(response))).getBody();
if (isGzip()) {
if (decompressResponse && isGzip()) {
return getDecompressedBytes(body);
}
return body;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,12 @@ protected HttpResponse sendAndReceive(@Nullable final String body) throws IOExce
}

return client.execute(create(request),
new LogbookHttpAsyncResponseConsumer<>(createConsumer()), callback).get();
new LogbookHttpAsyncResponseConsumer<>(createConsumer(), false), callback).get();
}

@Test
void shouldWrapIOException() throws IOException {
final HttpAsyncResponseConsumer<HttpResponse> unit = new LogbookHttpAsyncResponseConsumer<>(createConsumer());
final HttpAsyncResponseConsumer<HttpResponse> unit = new LogbookHttpAsyncResponseConsumer<>(createConsumer(), false);

final BasicHttpContext context = new BasicHttpContext();
context.setAttribute(Attributes.STAGE, stage);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public final class LogbookHttpInterceptorsGzipTest extends AbstractHttpTest {

private final CloseableHttpClient client = HttpClientBuilder.create()
.addInterceptorFirst(new LogbookHttpRequestInterceptor(logbook))
.addInterceptorFirst(new LogbookHttpResponseInterceptor())
.addInterceptorFirst(new LogbookHttpResponseInterceptor(true))
.build();

@AfterEach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void defaultBehaviour() {

private final CloseableHttpClient client = HttpClientBuilder.create()
.addInterceptorFirst(new LogbookHttpRequestInterceptor(logbook))
.addInterceptorFirst(new LogbookHttpResponseInterceptor())
.addInterceptorFirst(new LogbookHttpResponseInterceptor(false))
.build();

@AfterEach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public final class LogbookHttpInterceptorsTest extends AbstractHttpTest {

private final CloseableHttpClient client = HttpClientBuilder.create()
.addInterceptorFirst(new LogbookHttpRequestInterceptor(logbook))
.addInterceptorFirst(new LogbookHttpResponseInterceptor())
.addInterceptorFirst(new LogbookHttpResponseInterceptor(false))
.build();

@AfterEach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ final class RemoteResponseTest {

private final BasicHttpEntity entity = new BasicHttpEntity();
private final HttpResponse delegate = new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 1), 200, "OK");
private final RemoteResponse unit = new RemoteResponse(delegate);
private final RemoteResponse unit = new RemoteResponse(delegate, false);

@BeforeEach
void setUpResponseBody() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,8 @@ public LogbookHttpRequestInterceptor logbookHttpRequestInterceptor(final Logbook

@Bean
@ConditionalOnMissingBean(LogbookHttpResponseInterceptor.class)
public LogbookHttpResponseInterceptor logbookHttpResponseInterceptor() {
return new LogbookHttpResponseInterceptor();
public LogbookHttpResponseInterceptor logbookHttpResponseInterceptor(@Value("${logbook.httpclient.decompress-response:false}") final boolean decompressResponse) {
return new LogbookHttpResponseInterceptor(decompressResponse);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@
"type": "java.lang.Integer",
"defaultValue": 400,
"description": "Minimum status code for conditional strategies."
},
{
"name": "logbook.httpclient.decompress-response",
"type": "java.lang.Boolean",
"defaultValue": false,
"description": "Enables/disables additional decompression process for HttpClient with gzip encoded body (to logging purposes only)."
}
]
}

0 comments on commit 0f44cb4

Please sign in to comment.