diff --git a/quarkus-automaton/src/main/java/de/galabau/dateieingang/ords/OrdsClient.java b/quarkus-automaton/src/main/java/de/galabau/dateieingang/ords/OrdsClient.java index f43b61f..41b2252 100644 --- a/quarkus-automaton/src/main/java/de/galabau/dateieingang/ords/OrdsClient.java +++ b/quarkus-automaton/src/main/java/de/galabau/dateieingang/ords/OrdsClient.java @@ -4,6 +4,7 @@ import jakarta.ws.rs.HeaderParam; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.core.Response; +import org.eclipse.microprofile.rest.client.annotation.RegisterProvider; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; /** @@ -13,6 +14,7 @@ import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; * Weitere Endpunkte zukünftiger Pipelines werden hier als neue Methoden ergänzt. */ @RegisterRestClient(configKey = "ords-client") +@RegisterProvider(OrdsLoggingFilter.class) public interface OrdsClient { /** diff --git a/quarkus-automaton/src/main/java/de/galabau/dateieingang/ords/OrdsLoggingFilter.java b/quarkus-automaton/src/main/java/de/galabau/dateieingang/ords/OrdsLoggingFilter.java new file mode 100644 index 0000000..a1ba9c1 --- /dev/null +++ b/quarkus-automaton/src/main/java/de/galabau/dateieingang/ords/OrdsLoggingFilter.java @@ -0,0 +1,54 @@ +package de.galabau.dateieingang.ords; + +import io.quarkus.logging.Log; +import jakarta.ws.rs.client.ClientRequestContext; +import jakarta.ws.rs.client.ClientRequestFilter; +import jakarta.ws.rs.client.ClientResponseContext; +import jakarta.ws.rs.client.ClientResponseFilter; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; + +/** Loggt ORDS-Requests und -Responses im selben Format wie der DefaultClientLogger, maskiert jedoch den X-Api-Key-Header. */ +public class OrdsLoggingFilter implements ClientRequestFilter, ClientResponseFilter { + + @Override + public void filter(ClientRequestContext ctx) { + String headers = ctx.getHeaders().entrySet().stream() + .map(e -> e.getKey() + "=" + ( + "X-Api-Key".equals(e.getKey()) + ? mask(String.valueOf(e.getValue().getFirst())) + : e.getValue().getFirst() + )) + .collect(Collectors.joining(" ")); + + String body = ctx.hasEntity() ? "" : "Empty body"; + + Log.infof("Request: %s %s Headers[%s], %s", ctx.getMethod(), ctx.getUri(), headers, body); + } + + @Override + public void filter(ClientRequestContext req, ClientResponseContext res) throws IOException { + String headers = res.getHeaders().entrySet().stream() + .map(e -> e.getKey() + "=" + e.getValue().getFirst()) + .collect(Collectors.joining(" ")); + + String body = ""; + if (res.hasEntity()) { + byte[] bytes = res.getEntityStream().readAllBytes(); + body = new String(bytes, StandardCharsets.UTF_8); + res.setEntityStream(new ByteArrayInputStream(bytes)); + } + + Log.infof("Response: %s %s, Status[%d %s], Headers[%s], Body:\n%s", + req.getMethod(), req.getUri(), + res.getStatus(), res.getStatusInfo().getReasonPhrase(), + headers, body); + } + + private static String mask(String value) { + return value.substring(0, Math.min(4, value.length())) + "***"; + } +}