feat(client-logger): redact headers based on configuration
All checks were successful
Build / build (pull_request) Successful in 2m9s

This commit is contained in:
Jorge Bornhausen 2025-07-30 14:44:49 +02:00
parent d1acb1a0ee
commit 21913626ad
Signed by: jorge.bornhausen
SSH key fingerprint: SHA256:X2ootOwvCeP4FoNfmVUFIKIbhq95tAgnt7Oqg3x+lfs
12 changed files with 286 additions and 5 deletions

View file

@ -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<String, String> getConfigOverrides() {
return Map.of("quarkus.log.category.\"ch.phoenix.oss.quarkus.commons.client.logger\".level", "INFO");
}
}

View file

@ -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", "");
}
}

View file

@ -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", "");
}
}

View file

@ -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<String, String> getConfigOverrides() {
return Map.of("quarkus.rest-client.logging.scope", "none");
}
}

View file

@ -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", "");
}
}

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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