diff --git a/http-client/src/main/java/io/avaje/http/client/DHttpClientBuilder.java b/http-client/src/main/java/io/avaje/http/client/DHttpClientBuilder.java index f7e8a9ce..0a3d5dec 100644 --- a/http-client/src/main/java/io/avaje/http/client/DHttpClientBuilder.java +++ b/http-client/src/main/java/io/avaje/http/client/DHttpClientBuilder.java @@ -10,8 +10,10 @@ import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -50,6 +52,7 @@ final class DHttpClientBuilder implements HttpClient.Builder, HttpClient.Builder private final List interceptors = new ArrayList<>(); private final List listeners = new ArrayList<>(); + private final Set suppressed = new HashSet<>(); private void configureRetryHandler(BeanScope beanScope) { beanScope.getOptional(RetryHandler.class) @@ -170,7 +173,7 @@ private DHttpClientContext buildClient() { final var httpClient = client != null ? client : defaultClient(); if (requestLogging) { // register the built-in request/response logging - this.listeners.add(new RequestLogger()); + this.listeners.add(new RequestLogger("\n", suppressed)); } if (bodyAdapter == null) { bodyAdapter = defaultBodyAdapter(); @@ -317,6 +320,12 @@ public HttpClient.Builder priority(int priority) { return this; } + @Override + public HttpClient.Builder suppressHeader(String header) { + this.suppressed.add(header); + return this; + } + @Override public HttpClient.Builder.State state() { return this; diff --git a/http-client/src/main/java/io/avaje/http/client/HttpClient.java b/http-client/src/main/java/io/avaje/http/client/HttpClient.java index 2543d967..7d7e9745 100644 --- a/http-client/src/main/java/io/avaje/http/client/HttpClient.java +++ b/http-client/src/main/java/io/avaje/http/client/HttpClient.java @@ -321,6 +321,13 @@ interface Builder { */ Builder configureWith(BeanScope beanScope); + /** + * Suppress logging of the given header name. + * + *

Authorization headers are suppressed by default. + */ + Builder suppressHeader(String header); + /** * Return the state of the builder. */ diff --git a/http-client/src/main/java/io/avaje/http/client/RequestLogger.java b/http-client/src/main/java/io/avaje/http/client/RequestLogger.java index 391d04b6..c3c3de42 100644 --- a/http-client/src/main/java/io/avaje/http/client/RequestLogger.java +++ b/http-client/src/main/java/io/avaje/http/client/RequestLogger.java @@ -1,15 +1,17 @@ package io.avaje.http.client; -import io.avaje.applog.AppLog; - import java.lang.System.Logger.Level; import java.net.http.HttpHeaders; import java.net.http.HttpRequest; import java.net.http.HttpResponse; +import java.util.Collection; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import io.avaje.applog.AppLog; + /** * Logs request and response details for debug logging purposes using System.Logger. *

@@ -31,6 +33,7 @@ public class RequestLogger implements RequestListener { private static final System.Logger log = AppLog.getLogger("io.avaje.http.client.RequestLogger"); private final String delimiter; + private final Set suppressedHeaders = new HashSet<>(); /** * Create using the {@literal \n} new line character. @@ -43,7 +46,16 @@ public RequestLogger() { * Create with a given line delimiter. */ public RequestLogger(String delimiter) { + this(delimiter, List.of()); + } + + /** + * Create with a given line delimiter and set of headers to suppress. + */ + public RequestLogger(String delimiter, Collection suppressedHeaders) { this.delimiter = delimiter; + this.suppressedHeaders.add(DHttpClientContext.AUTHORIZATION); + this.suppressedHeaders.addAll(suppressedHeaders); } @Override @@ -91,6 +103,6 @@ private void headers(StringBuilder sb, String label, HttpHeaders headers) { } boolean obfuscate(String key) { - return DHttpClientContext.AUTHORIZATION.equals(key); + return suppressedHeaders.contains(key); } }