From f7895cf961cd7857ba2ef2351d1fcd341c04a802 Mon Sep 17 00:00:00 2001 From: Andreas Dinauer Date: Sat, 18 Apr 2026 17:08:28 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=9A=A7=20Improved=20access=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/dev/dinauer/oidcproxy/Resource.java | 15 ++++--- .../dinauer/oidcproxy/proxy/AccessLog.java | 41 +++++++++++++++++++ .../oidcproxy/proxy/ForwardService.java | 10 +++-- .../oidcproxy/proxy/TimedHttpResponse.java | 7 ++++ .../proxy/exception/ProxyHttpException.java | 9 +++- .../oidcproxy/request/HttpRequestBuilder.java | 19 ++++----- 6 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 src/main/java/dev/dinauer/oidcproxy/proxy/AccessLog.java create mode 100644 src/main/java/dev/dinauer/oidcproxy/proxy/TimedHttpResponse.java diff --git a/src/main/java/dev/dinauer/oidcproxy/Resource.java b/src/main/java/dev/dinauer/oidcproxy/Resource.java index 7a7572e..ad29f44 100644 --- a/src/main/java/dev/dinauer/oidcproxy/Resource.java +++ b/src/main/java/dev/dinauer/oidcproxy/Resource.java @@ -1,8 +1,10 @@ package dev.dinauer.oidcproxy; import dev.dinauer.oidcproxy.callback.CallbackService; +import dev.dinauer.oidcproxy.proxy.AccessLog; import dev.dinauer.oidcproxy.proxy.ForwardService; import dev.dinauer.oidcproxy.proxy.ResponseHandler; +import dev.dinauer.oidcproxy.proxy.TimedHttpResponse; import dev.dinauer.oidcproxy.proxy.exception.ProxyHttpException; import dev.dinauer.oidcproxy.proxy.exception.TokenNotFoundException; import dev.dinauer.oidcproxy.startup.PathConverter; @@ -38,6 +40,9 @@ public class Resource @Inject LogoutService logoutService; + @Inject + AccessLog accessLog; + @Route(path = "/auth/callback", order = 0) @Blocking public void callback(@Context RoutingContext context) @@ -72,16 +77,16 @@ public class Resource private void route(RoutingContext context, String path, ProxyRoute route) { List requestSegments = PathConverter.toSegments(path); - LOG.info("Matched route with target '{}'", route.target()); try { String targetURI = route.target() + PathConverter.toPath(requestSegments); - HttpResponse response = forwardService.send(context, targetURI, route.strategy()); - ResponseHandler.success(context, response); + TimedHttpResponse response = forwardService.send(context, targetURI, route.strategy()); + accessLog.log(AccessLog.Type.INFO, context, PathConverter.toPath(requestSegments), route.target(), response.response().statusCode(), response.time()); + ResponseHandler.success(context, response.response()); } catch (ProxyHttpException e) { - LOG.error("Upstream returned error status {}.", e.getStatusCode(), e); + accessLog.log(AccessLog.Type.ERROR, context, PathConverter.toPath(requestSegments), route.target(), e.getStatusCode(), e.getTime()); ResponseHandler.error(context, e.getStatusCode()); } catch (TokenNotFoundException e) @@ -97,7 +102,7 @@ public class Resource } catch (Exception e) { - LOG.error("Error occurred on upstream.", e); + accessLog.logUpstream(context, PathConverter.toPath(requestSegments), route.target()); ResponseHandler.error(context, 502); } } diff --git a/src/main/java/dev/dinauer/oidcproxy/proxy/AccessLog.java b/src/main/java/dev/dinauer/oidcproxy/proxy/AccessLog.java new file mode 100644 index 0000000..f674585 --- /dev/null +++ b/src/main/java/dev/dinauer/oidcproxy/proxy/AccessLog.java @@ -0,0 +1,41 @@ +package dev.dinauer.oidcproxy.proxy; + +import dev.dinauer.oidcproxy.startup.PathConverter; +import io.vertx.ext.web.RoutingContext; +import jakarta.enterprise.context.ApplicationScoped; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@ApplicationScoped +public class AccessLog +{ + private static final Logger LOG = LoggerFactory.getLogger(AccessLog.class); + + public void log(Type type, RoutingContext context, String request, String target, int statusCode, long time) + { + String log = String.format("[%s] [%s %s] %s - %s - %sms", context.request().remoteAddress().host(), context.request().method().toString().toUpperCase(), request, target, statusCode, time); + switch (type) + { + case INFO -> + { + LOG.info(log); + } + case ERROR -> + { + LOG.error(log); + } + } + } + + public void logUpstream(RoutingContext context, String request, String target) + { + String log = String.format("[%s] [%s %s] %s - UPSTREAM ERROR", context.request().remoteAddress().host(), context.request().method().toString().toUpperCase(), request, target); + LOG.error(log); + } + + + public enum Type + { + INFO, ERROR + } +} diff --git a/src/main/java/dev/dinauer/oidcproxy/proxy/ForwardService.java b/src/main/java/dev/dinauer/oidcproxy/proxy/ForwardService.java index cf4595c..158b23c 100644 --- a/src/main/java/dev/dinauer/oidcproxy/proxy/ForwardService.java +++ b/src/main/java/dev/dinauer/oidcproxy/proxy/ForwardService.java @@ -23,7 +23,7 @@ public class ForwardService @Inject HeaderFilter headerFilter; - public HttpResponse send(RoutingContext context, String route, String strategy) throws IOException, InterruptedException, ProxyHttpException, TokenNotFoundException + public TimedHttpResponse send(RoutingContext context, String route, String strategy) throws IOException, InterruptedException, ProxyHttpException, TokenNotFoundException { HttpRequestBuilder builder = HttpRequestBuilder.create(); builder.setUri(route); @@ -32,12 +32,16 @@ public class ForwardService builder.setHeaders(headerFilter.filter(context.request(), strategy)); builder.setBody(extractBody(context)); + long start = System.currentTimeMillis(); HttpResponse response = CLIENT.send(builder.build(), HttpResponse.BodyHandlers.ofByteArray()); + long end = System.currentTimeMillis(); + + long time = end - start; if (response.statusCode() < 400) { - return response; + return new TimedHttpResponse<>(time, response); } - throw new ProxyHttpException(response.statusCode()); + throw new ProxyHttpException(time, response.statusCode()); } private byte[] extractBody(RoutingContext context) diff --git a/src/main/java/dev/dinauer/oidcproxy/proxy/TimedHttpResponse.java b/src/main/java/dev/dinauer/oidcproxy/proxy/TimedHttpResponse.java new file mode 100644 index 0000000..6167811 --- /dev/null +++ b/src/main/java/dev/dinauer/oidcproxy/proxy/TimedHttpResponse.java @@ -0,0 +1,7 @@ +package dev.dinauer.oidcproxy.proxy; + +import java.net.http.HttpResponse; + +public record TimedHttpResponse(long time, HttpResponse response) +{ +} diff --git a/src/main/java/dev/dinauer/oidcproxy/proxy/exception/ProxyHttpException.java b/src/main/java/dev/dinauer/oidcproxy/proxy/exception/ProxyHttpException.java index 5bf34a9..b9eefd4 100644 --- a/src/main/java/dev/dinauer/oidcproxy/proxy/exception/ProxyHttpException.java +++ b/src/main/java/dev/dinauer/oidcproxy/proxy/exception/ProxyHttpException.java @@ -2,13 +2,20 @@ package dev.dinauer.oidcproxy.proxy.exception; public class ProxyHttpException extends Exception { + private final long time; private final int statusCode; - public ProxyHttpException(int statusCode) + public ProxyHttpException(long time, int statusCode) { + this.time = time; this.statusCode = statusCode; } + public long getTime() + { + return time; + } + public int getStatusCode() { return statusCode; diff --git a/src/main/java/dev/dinauer/oidcproxy/request/HttpRequestBuilder.java b/src/main/java/dev/dinauer/oidcproxy/request/HttpRequestBuilder.java index b940f08..6d860f4 100644 --- a/src/main/java/dev/dinauer/oidcproxy/request/HttpRequestBuilder.java +++ b/src/main/java/dev/dinauer/oidcproxy/request/HttpRequestBuilder.java @@ -10,10 +10,14 @@ import java.net.http.HttpRequest; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; public class HttpRequestBuilder { + private static final Set DISALLOWED_HEADERS = Set.of("connection", "content-length", "expect", "host", "upgrade"); + private static final Logger LOG = LoggerFactory.getLogger(HttpRequestBuilder.class); private String method; @@ -57,20 +61,11 @@ public class HttpRequestBuilder HttpRequest.Builder builder = HttpRequest.newBuilder(); builder.uri(buildURI(this.uri, this.params)); builder.method(method, buildBody(body)); - - if (this.headers != null) + for (Map.Entry element : Optional.ofNullable(this.headers).orElse(List.of())) { - for (Map.Entry element : this.headers) + if (!DISALLOWED_HEADERS.contains(element.getKey())) { - try - { - builder.setHeader(element.getKey(), element.getValue()); - LOG.info("added header " + element.getKey()); - } - catch (Exception e) - { - LOG.info("Failed to add header.", e); - } + builder.setHeader(element.getKey(), element.getValue()); } } return builder.build();