All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.undertow.server.handlers.accesslog.AccessLogHandler Maven / Gradle / Ivy

There is a newer version: 2.3.18.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2014 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package io.undertow.server.handlers.accesslog;


import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import io.undertow.attribute.ExchangeAttribute;
import io.undertow.attribute.ExchangeAttributes;
import io.undertow.attribute.SubstituteEmptyWrapper;
import io.undertow.predicate.Predicate;
import io.undertow.predicate.Predicates;
import io.undertow.server.ExchangeCompletionListener;
import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.server.handlers.builder.HandlerBuilder;

/**
 * Access log handler. This handler will generate access log messages based on the provided format string,
 * and pass these messages into the provided {@link AccessLogReceiver}.
 * 

* This handler can log any attribute that is provides via the {@link io.undertow.attribute.ExchangeAttribute} * mechanism. A general guide to the most common attribute is provided before, however this mechanism is extensible. *

*

*

This factory produces token handlers for the following patterns

*
    *
  • %a - Remote IP address *
  • %A - Local IP address *
  • %b - Bytes sent, excluding HTTP headers, or '-' if no bytes * were sent *
  • %B - Bytes sent, excluding HTTP headers *
  • %h - Remote host name *
  • %H - Request protocol *
  • %l - Remote logical username from identd (always returns '-') *
  • %m - Request method *
  • %o - Obfuscated remote IP address (IPv4: last byte removed, * IPv6: cut off after second colon, ie. '1.2.3.' or 'fe08:44:') *
  • %p - Local port *
  • %q - Query string (excluding the '?' character) *
  • %r - First line of the request *
  • %s - HTTP status code of the response *
  • %t - Date and time, in Common Log Format format *
  • %u - Remote user that was authenticated *
  • %U - Requested URL path *
  • %v - Local server name *
  • %D - Time taken to process the request, in millis *
  • %T - Time taken to process the request, in seconds *
  • %I - current Request thread name (can compare later with stacktraces) *
*

In addition, the caller can specify one of the following aliases for * commonly utilized patterns:

*
    *
  • common - %h %l %u %t "%r" %s %b *
  • combined - * %h %l %u %t "%r" %s %b "%{i,Referer}" "%{i,User-Agent}" *
  • commonobf - %o %l %u %t "%r" %s %b *
  • combinedobf - * %o %l %u %t "%r" %s %b "%{i,Referer}" "%{i,User-Agent}" *
*

*

* There is also support to write information from the cookie, incoming * header, or the session
* It is modeled after the apache syntax: *

    *
  • %{i,xxx} for incoming headers *
  • %{o,xxx} for outgoing response headers *
  • %{c,xxx} for a specific cookie *
  • %{r,xxx} xxx is an attribute in the ServletRequest *
  • %{s,xxx} xxx is an attribute in the HttpSession *
* * @author Stuart Douglas */ public class AccessLogHandler implements HttpHandler { private final HttpHandler next; private final AccessLogReceiver accessLogReceiver; private final String formatString; private final ExchangeAttribute tokens; private final ExchangeCompletionListener exchangeCompletionListener = new AccessLogCompletionListener(); private final Predicate predicate; public AccessLogHandler(final HttpHandler next, final AccessLogReceiver accessLogReceiver, final String formatString, ClassLoader classLoader) { this(next, accessLogReceiver, formatString, classLoader, Predicates.truePredicate()); } public AccessLogHandler(final HttpHandler next, final AccessLogReceiver accessLogReceiver, final String formatString, ClassLoader classLoader, Predicate predicate) { this.next = next; this.accessLogReceiver = accessLogReceiver; this.predicate = predicate; this.formatString = handleCommonNames(formatString); this.tokens = ExchangeAttributes.parser(classLoader, new SubstituteEmptyWrapper("-")).parse(this.formatString); } public AccessLogHandler(final HttpHandler next, final AccessLogReceiver accessLogReceiver, String formatString, final ExchangeAttribute attribute) { this(next, accessLogReceiver, formatString, attribute, Predicates.truePredicate()); } public AccessLogHandler(final HttpHandler next, final AccessLogReceiver accessLogReceiver, String formatString, final ExchangeAttribute attribute, Predicate predicate) { this.next = next; this.accessLogReceiver = accessLogReceiver; this.predicate = predicate; this.formatString = handleCommonNames(formatString); this.tokens = attribute; } private static String handleCommonNames(String formatString) { if(formatString.equals("common")) { return "%h %l %u %t \"%r\" %s %b"; } else if (formatString.equals("combined")) { return "%h %l %u %t \"%r\" %s %b \"%{i,Referer}\" \"%{i,User-Agent}\""; } else if(formatString.equals("commonobf")) { return "%o %l %u %t \"%r\" %s %b"; } else if (formatString.equals("combinedobf")) { return "%o %l %u %t \"%r\" %s %b \"%{i,Referer}\" \"%{i,User-Agent}\""; } return formatString; } @Override public void handleRequest(final HttpServerExchange exchange) throws Exception { exchange.addExchangeCompleteListener(exchangeCompletionListener); next.handleRequest(exchange); } private class AccessLogCompletionListener implements ExchangeCompletionListener { @Override public void exchangeEvent(final HttpServerExchange exchange, final NextListener nextListener) { try { if(predicate == null || predicate.resolve(exchange)) { accessLogReceiver.logMessage(tokens.readAttribute(exchange)); } } finally { nextListener.proceed(); } } } @Override public String toString() { return "AccessLogHandler{" + "formatString='" + formatString + '\'' + '}'; } public static class Builder implements HandlerBuilder { @Override public String name() { return "access-log"; } @Override public Map> parameters() { Map> params = new HashMap<>(); params.put("format", String.class); params.put("category", String.class); return params; } @Override public Set requiredParameters() { return Collections.singleton("format"); } @Override public String defaultParameter() { return "format"; } @Override public HandlerWrapper build(Map config) { return new Wrapper((String) config.get("format"), (String) config.get("category")); } } private static class Wrapper implements HandlerWrapper { private final String format; private final String category; private Wrapper(String format, String category) { this.format = format; this.category = category; } @Override public HttpHandler wrap(HttpHandler handler) { if (category == null || category.trim().isEmpty()) { return new AccessLogHandler(handler, new JBossLoggingAccessLogReceiver(), format, Wrapper.class.getClassLoader()); } else { return new AccessLogHandler(handler, new JBossLoggingAccessLogReceiver(category), format, Wrapper.class.getClassLoader()); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy