Add request filter.

This commit is contained in:
Stephan Schnabel 2020-08-20 19:40:48 +02:00
parent c4b1d1d2f6
commit c3d38e2d11
Signed by: stephan.schnabel
GPG key ID: F74FE2422AA07290
12 changed files with 500 additions and 0 deletions

View file

@ -0,0 +1,75 @@
package io.kokuwa.micronaut.logging.request;
import java.util.Optional;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.reactivestreams.Publisher;
import org.slf4j.MDC;
import ch.qos.logback.classic.turbo.TurboFilter;
import io.kokuwa.micronaut.logging.LogbackUtil;
import io.micronaut.context.annotation.Requires;
import io.micronaut.context.annotation.Value;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MutableHttpResponse;
import io.micronaut.http.annotation.Filter;
import io.micronaut.http.filter.HttpServerFilter;
import io.micronaut.http.filter.ServerFilterChain;
import io.micronaut.http.filter.ServerFilterPhase;
import io.micronaut.runtime.server.EmbeddedServer;
/**
* Http request logging filter.
*
* @author Stephan Schnabel
*/
@Requires(beans = EmbeddedServer.class)
@Requires(property = HeaderLoggingHttpFilter.ENABLED, notEquals = "false")
@Filter("${" + HeaderLoggingHttpFilter.PREFIX + ".pattern:" + HeaderLoggingHttpFilter.DEFAULT_PATTERN + ":/**}")
public class HeaderLoggingHttpFilter implements HttpServerFilter {
public static final String PREFIX = "logger.request.header";
public static final String ENABLED = PREFIX + ".enabled";
public static final String MDC_FILTER = PREFIX + ".filter";
public static final String MDC_KEY = "level";
public static final String DEFAULT_HEADER = "x-log-level";
public static final String DEFAULT_PATTERN = "/**";
public static final int DEFAULT_ORDER = ServerFilterPhase.FIRST.before();
private final LogbackUtil logback;
private final String header;
private final int order;
public HeaderLoggingHttpFilter(
LogbackUtil logback,
@Value("${" + PREFIX + ".header:" + DEFAULT_HEADER + "}") String header,
@Value("${" + PREFIX + ".order}") Optional<Integer> order) {
this.logback = logback;
this.header = header;
this.order = order.orElse(DEFAULT_ORDER);
}
@PostConstruct
void startTurbofilter() {
logback.getTurboFilter(HeaderLoggingTurboFilter.class, MDC_FILTER, HeaderLoggingTurboFilter::new).start();
}
@PreDestroy
void stopTurbofilter() {
logback.getTurboFilter(HeaderLoggingTurboFilter.class, MDC_FILTER).ifPresent(TurboFilter::stop);
}
@Override
public int getOrder() {
return order;
}
@Override
public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
request.getHeaders().getFirst(header).ifPresent(level -> MDC.put(MDC_KEY, level));
return chain.proceed(request);
}
}

View file

@ -0,0 +1,32 @@
package io.kokuwa.micronaut.logging.request;
import org.slf4j.MDC;
import org.slf4j.Marker;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.turbo.TurboFilter;
import ch.qos.logback.core.spi.FilterReply;
/**
* Filter for log levels based on MDC.
*
* @author Stephan Schnabel
*/
public class HeaderLoggingTurboFilter extends TurboFilter {
@Override
public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable t) {
if (!isStarted()) {
return FilterReply.NEUTRAL;
}
var value = MDC.get(HeaderLoggingHttpFilter.MDC_KEY);
if (value == null) {
return FilterReply.NEUTRAL;
}
return level.isGreaterOrEqual(Level.valueOf(value)) ? FilterReply.ACCEPT : FilterReply.NEUTRAL;
}
}

View file

@ -0,0 +1,55 @@
package io.kokuwa.micronaut.logging.request;
import java.util.Optional;
import org.reactivestreams.Publisher;
import org.slf4j.MDC;
import io.micronaut.context.annotation.Requires;
import io.micronaut.context.annotation.Value;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.MutableHttpResponse;
import io.micronaut.http.annotation.Filter;
import io.micronaut.http.filter.HttpServerFilter;
import io.micronaut.http.filter.ServerFilterChain;
import io.micronaut.http.filter.ServerFilterPhase;
import io.micronaut.runtime.server.EmbeddedServer;
/**
* Http request principal filter.
*
* @author Stephan Schnabel
*/
@Requires(beans = EmbeddedServer.class)
@Requires(property = PrincipalHttpFilter.ENABLED, notEquals = "false")
@Filter("${" + PrincipalHttpFilter.PREFIX + ".pattern:" + PrincipalHttpFilter.DEFAULT_PATTERN + ":/**}")
public class PrincipalHttpFilter implements HttpServerFilter {
public static final String PREFIX = "logger.request.principal";
public static final String ENABLED = PREFIX + ".enabled";
public static final String DEFAULT_KEY = "principal";
public static final String DEFAULT_PATTERN = "/**";
public static final int DEFAULT_ORDER = ServerFilterPhase.SECURITY.after();
private final String key;
private final int order;
public PrincipalHttpFilter(
@Value("${" + PREFIX + ".key:" + DEFAULT_KEY + "}") String key,
@Value("${" + PREFIX + ".order}") Optional<Integer> order) {
this.key = key;
this.order = order.orElse(DEFAULT_ORDER);
}
@Override
public int getOrder() {
return order;
}
@Override
public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
request.getUserPrincipal().ifPresent(princial -> MDC.put(key, princial.getName()));
return chain.proceed(request);
}
}