diff --git a/quarkus-client-logger/pom.xml b/quarkus-client-logger/pom.xml
index 81aa2e0..9306ab4 100644
--- a/quarkus-client-logger/pom.xml
+++ b/quarkus-client-logger/pom.xml
@@ -16,6 +16,16 @@
io.quarkus
quarkus-rest-client
+
+ io.quarkus
+ quarkus-config-yaml
+ test
+
+
+ io.quarkus
+ quarkus-rest-jackson
+ test
+
@@ -40,7 +50,7 @@
INSTRUCTION
COVEREDRATIO
- 1
+ 0.92
diff --git a/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/LowerCaseStringConverter.java b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/LowerCaseStringConverter.java
new file mode 100644
index 0000000..498e318
--- /dev/null
+++ b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/LowerCaseStringConverter.java
@@ -0,0 +1,10 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import org.eclipse.microprofile.config.spi.Converter;
+
+public class LowerCaseStringConverter implements Converter {
+ @Override
+ public String convert(String value) throws IllegalArgumentException, NullPointerException {
+ return value.toLowerCase();
+ }
+}
diff --git a/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLogger.java b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLogger.java
index 3061c09..cb2b63b 100644
--- a/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLogger.java
+++ b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLogger.java
@@ -6,23 +6,36 @@ import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpClientResponse;
import jakarta.enterprise.context.Dependent;
-import jakarta.ws.rs.core.HttpHeaders;
+import jakarta.inject.Inject;
import java.util.Map;
+import java.util.Set;
import org.jboss.logging.Logger;
import org.jboss.resteasy.reactive.client.api.ClientLogger;
/**
* This is based on org.jboss.resteasy.reactive.client.logging.DefaultClientLogger,
- * with the only change being that the value of "Authorization" header, when present,
- * is redacted.
+ * with the only change being that headers are redacted based on the Set provided
+ * by the configuration.
*/
@Dependent
public class RedactingClientLogger implements ClientLogger {
private static final Logger log = Logger.getLogger(RedactingClientLogger.class);
+ private static final String REDACTED_VALUE = "*****";
+
+ private final Set redactedHeaders;
+
private int bodySize;
+ @Inject
+ public RedactingClientLogger(RedactingClientLoggerConfiguration configuration) {
+ this.redactedHeaders = configuration
+ .headers()
+ .redact()
+ .orElse(RedactingClientLoggerConfiguration.Headers.DEFAULT_REDACTED_HEADERS);
+ }
+
@Override
public void setBodySize(int bodySize) {
this.bodySize = bodySize;
@@ -97,7 +110,7 @@ public class RedactingClientLogger implements ClientLogger {
}
var key = entry.getKey();
- var value = HttpHeaders.AUTHORIZATION.equalsIgnoreCase(key) ? "*****" : entry.getValue();
+ var value = redactedHeaders.contains(key.toLowerCase()) ? REDACTED_VALUE : entry.getValue();
sb.append(key).append('=').append(value);
}
diff --git a/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerConfiguration.java b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerConfiguration.java
new file mode 100644
index 0000000..24fa05f
--- /dev/null
+++ b/quarkus-client-logger/src/main/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerConfiguration.java
@@ -0,0 +1,20 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithConverter;
+import jakarta.ws.rs.core.HttpHeaders;
+import java.util.Optional;
+import java.util.Set;
+
+@ConfigMapping(prefix = "phoenix.client-logger")
+public interface RedactingClientLoggerConfiguration {
+
+ Headers headers();
+
+ interface Headers {
+
+ Set DEFAULT_REDACTED_HEADERS = Set.of(HttpHeaders.AUTHORIZATION.toLowerCase());
+
+ Optional> redact();
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelProfile.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelProfile.java
new file mode 100644
index 0000000..35acb14
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelProfile.java
@@ -0,0 +1,12 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+import java.util.Map;
+
+public class InfoLevelProfile implements QuarkusTestProfile {
+
+ @Override
+ public Map getConfigOverrides() {
+ return Map.of("quarkus.log.category.\"ch.phoenix.oss.quarkus.commons.client.logger\".level", "INFO");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelTest.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelTest.java
new file mode 100644
index 0000000..c6b27ef
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/InfoLevelTest.java
@@ -0,0 +1,44 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import jakarta.inject.Inject;
+import java.net.URI;
+import java.util.Optional;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(InfoLevelProfile.class)
+class InfoLevelTest {
+
+ @Inject
+ @RestClient
+ TestClient injectedClient;
+
+ TestClient builtClient = QuarkusRestClientBuilder.newBuilder()
+ .clientLogger(new RedactingClientLogger(() -> Optional::empty))
+ .baseUri(URI.create("http://localhost:8087"))
+ .build(TestClient.class);
+
+ @Test
+ void getWithInjectedClient() {
+ injectedClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted");
+ }
+
+ @Test
+ void getWithBuiltClientAndEmptyConfig() {
+ builtClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted");
+ }
+
+ @Test
+ void postWithInjectedClient() {
+ injectedClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted", "body");
+ }
+
+ @Test
+ void postWithBuiltClientAndEmptyConfig() {
+ builtClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted", "");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerTest.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerTest.java
new file mode 100644
index 0000000..01e9389
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/RedactingClientLoggerTest.java
@@ -0,0 +1,47 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
+import io.quarkus.test.junit.QuarkusTest;
+import jakarta.inject.Inject;
+import java.net.URI;
+import java.util.Optional;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+class RedactingClientLoggerTest {
+
+ @Inject
+ @RestClient
+ TestClient injectedClient;
+
+ TestClient builtClient = QuarkusRestClientBuilder.newBuilder()
+ .clientLogger(new RedactingClientLogger(() -> Optional::empty))
+ .baseUri(URI.create("http://localhost:8087"))
+ .build(TestClient.class);
+
+ @Test
+ void getWithInjectedClient() {
+ injectedClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted");
+ }
+
+ @Test
+ void getWithBuiltClientAndEmptyConfig() {
+ builtClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted");
+ }
+
+ @Test
+ void postWithInjectedClient() {
+ injectedClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted", "body");
+ }
+
+ @Test
+ void postWithInjectedClientAndNullBody() {
+ injectedClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted", null);
+ }
+
+ @Test
+ void postWithBuiltClientAndEmptyConfig() {
+ builtClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted", "");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneProfile.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneProfile.java
new file mode 100644
index 0000000..42daa28
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneProfile.java
@@ -0,0 +1,12 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+import java.util.Map;
+
+public class ScopeNoneProfile implements QuarkusTestProfile {
+
+ @Override
+ public Map getConfigOverrides() {
+ return Map.of("quarkus.rest-client.logging.scope", "none");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneTest.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneTest.java
new file mode 100644
index 0000000..14538b2
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/ScopeNoneTest.java
@@ -0,0 +1,44 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import jakarta.inject.Inject;
+import java.net.URI;
+import java.util.Optional;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+import org.junit.jupiter.api.Test;
+
+@QuarkusTest
+@TestProfile(ScopeNoneProfile.class)
+class ScopeNoneTest {
+
+ @Inject
+ @RestClient
+ TestClient injectedClient;
+
+ TestClient builtClient = QuarkusRestClientBuilder.newBuilder()
+ .clientLogger(new RedactingClientLogger(() -> Optional::empty))
+ .baseUri(URI.create("http://localhost:8087"))
+ .build(TestClient.class);
+
+ @Test
+ void getWithInjectedClient() {
+ injectedClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted");
+ }
+
+ @Test
+ void getWithBuiltClientAndEmptyConfig() {
+ builtClient.get("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted");
+ }
+
+ @Test
+ void postWithInjectedClient() {
+ injectedClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "also redacted", "body");
+ }
+
+ @Test
+ void postWithBuiltClientAndEmptyConfig() {
+ builtClient.post("this will be redacted", "5c0d8e45-e402-4b71-8f84-24cc0cfd7eec", "not redacted", "");
+ }
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestClient.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestClient.java
new file mode 100644
index 0000000..79769ac
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestClient.java
@@ -0,0 +1,28 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+
+@SuppressWarnings("UastIncorrectHttpHeaderInspection")
+@RegisterRestClient(configKey = "test")
+public interface TestClient {
+
+ @GET
+ @Path("/")
+ @Produces(MediaType.TEXT_PLAIN)
+ String get(
+ @HeaderParam("Authorization") String authorization,
+ @HeaderParam("X-Request-ID") String requestId,
+ @HeaderParam("X-Something-Else") String somethingElse);
+
+ @POST
+ @Path("/")
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.TEXT_PLAIN)
+ String post(
+ @HeaderParam("Authorization") String authorization,
+ @HeaderParam("X-Request-ID") String requestId,
+ @HeaderParam("X-Something-Else") String somethingElse,
+ String body);
+}
diff --git a/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestResource.java b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestResource.java
new file mode 100644
index 0000000..c83bdd0
--- /dev/null
+++ b/quarkus-client-logger/src/test/java/ch/phoenix/oss/quarkus/commons/client/logger/TestResource.java
@@ -0,0 +1,21 @@
+package ch.phoenix.oss.quarkus.commons.client.logger;
+
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+
+@Path("/")
+public class TestResource {
+
+ @GET
+ @Produces(MediaType.TEXT_PLAIN)
+ public String get() {
+ return "get";
+ }
+
+ @POST
+ @Consumes(MediaType.TEXT_PLAIN)
+ @Produces(MediaType.TEXT_PLAIN)
+ public String post(String body) {
+ return body;
+ }
+}
diff --git a/quarkus-client-logger/src/test/resources/application.yaml b/quarkus-client-logger/src/test/resources/application.yaml
new file mode 100644
index 0000000..a02f41d
--- /dev/null
+++ b/quarkus-client-logger/src/test/resources/application.yaml
@@ -0,0 +1,20 @@
+quarkus:
+ http:
+ test-port: 8087
+ rest-client:
+ logging:
+ scope: request-response
+ body-limit: 10000
+ test:
+ url: http://localhost:${quarkus.http.test-port}
+ log:
+ category:
+ "ch.phoenix.oss.quarkus.commons.client.logger":
+ level: DEBUG
+
+phoenix:
+ client-logger:
+ headers:
+ redact:
+ - AUTHORIZATION
+ - X-SOMETHING-ELSE