Access Logging Tomcat

 

本来是http的请求 错误使用https方式请求 就会报该错
2021-01-08 17:45:35.984  INFO 10292 --- [nio-8080-exec-2] o.apache.coyote.http11.Http11Processor   : Error parsing HTTP request header
 Note: further occurrences of HTTP request parsing errors will be logged at DEBUG level.

java.lang.IllegalArgumentException: Invalid character found in method name [0x160x030x010x000xf70x010x000x000xf30x030x030xbf0xeb0xdf'0x150x97{0xbae0x8a0x16Q0xbaI;0x990x9bx0xcc0x9f0x1e0x0f0xa50x070x1dW0xd760x9e0x1b0x0dY]. HTTP method names must be tokens
    at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:417) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:261) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) [tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) [tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.41.jar:9.0.41]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_261]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_261]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.41.jar:9.0.41]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_261]

 

实际情况

发现是正常的http请求,发送为https请求。
例如正常路径为http://localhost:8080/xxxx,现在变成请求https://localhost:8080/xxxx就会报错。(似乎跟项目没有什么关系).

猜测

可能是tomcat8.5的keepalive有关,检测自己http协议的时候顺便检测了自己的https协议,有很多人遇到半夜报错或者隔了一段时间报错,目前这个bug没搜索到很多定论,可以尝试加tomcatconnection-timeout

parseRequestLine

报错的地方代码如下

org.apache.coyote.http11.Http11InputBuffer.parseRequestLine

 

    /**
     * Read the request line. This function is meant to be used during the
     * HTTP request header parsing. Do NOT attempt to read the request body
     * using it.
     *
     * @throws IOException If an exception occurs during the underlying socket
     * read operations, or if the given buffer is not big enough to accommodate
     * the whole line.
     * @return true if data is properly fed; false if no data is available
     * immediately and thread should be freed
     */
    boolean parseRequestLine(boolean keptAlive) throws IOException {

        // check state
        if (!parsingRequestLine) {
            return true;
        }
        //
        // Skipping blank lines
        //
        if (parsingRequestLinePhase < 2) {
            byte chr = 0;
            do {

                // Read new bytes if needed
                if (byteBuffer.position() >= byteBuffer.limit()) {
                    if (keptAlive) {
                        // Haven't read any request data yet so use the keep-alive
                        // timeout.
                        wrapper.setReadTimeout(wrapper.getEndpoint().getKeepAliveTimeout());
                    }
                    if (!fill(false)) {
                        // A read is pending, so no longer in initial state
                        parsingRequestLinePhase = 1;
                        return false;
                    }
                    // At least one byte of the request has been received.
                    // Switch to the socket timeout.
                    wrapper.setReadTimeout(wrapper.getEndpoint().getConnectionTimeout());
                }
                if (!keptAlive && byteBuffer.position() == 0 && byteBuffer.limit() >= CLIENT_PREFACE_START.length - 1) {
                    boolean prefaceMatch = true;
                    for (int i = 0; i < CLIENT_PREFACE_START.length && prefaceMatch; i++) {
                        if (CLIENT_PREFACE_START[i] != byteBuffer.get(i)) {
                            prefaceMatch = false;
                        }
                    }
                    if (prefaceMatch) {
                        // HTTP/2 preface matched
                        parsingRequestLinePhase = -1;
                        return false;
                    }
                }
                // Set the start time once we start reading data (even if it is
                // just skipping blank lines)
                if (request.getStartTime() < 0) {
                    request.setStartTime(System.currentTimeMillis());
                }
                chr = byteBuffer.get();
            } while ((chr == Constants.CR) || (chr == Constants.LF));
            byteBuffer.position(byteBuffer.position() - 1);

            parsingRequestLineStart = byteBuffer.position();
            parsingRequestLinePhase = 2;
            if (log.isDebugEnabled()) {
                log.debug("Received [" + new String(byteBuffer.array(), byteBuffer.position(), byteBuffer.remaining(),
                        StandardCharsets.ISO_8859_1) + "]");
            }
        }
        if (parsingRequestLinePhase == 2) {
            //
            // Reading the method name
            // Method name is a token
            //
            boolean space = false;
            while (!space) {
                // Read new bytes if needed
                if (byteBuffer.position() >= byteBuffer.limit()) {
                    if (!fill(false)) // request line parsing
                        return false;
                }
                // Spec says method name is a token followed by a single SP but
                // also be tolerant of multiple SP and/or HT.
                int pos = byteBuffer.position();
                byte chr = byteBuffer.get();
                if (chr == Constants.SP || chr == Constants.HT) {
                    space = true;
                    request.method().setBytes(byteBuffer.array(), parsingRequestLineStart,
                            pos - parsingRequestLineStart);
                } else if (!HttpParser.isToken(chr)) {
                    byteBuffer.position(byteBuffer.position() - 1);
                    throw new IllegalArgumentException(sm.getString("iib.invalidmethod"));
                }
            }
            parsingRequestLinePhase = 3;
        }
        if (parsingRequestLinePhase == 3) {
            // Spec says single SP but also be tolerant of multiple SP and/or HT
            boolean space = true;
            while (space) {
                // Read new bytes if needed
                if (byteBuffer.position() >= byteBuffer.limit()) {
                    if (!fill(false)) // request line parsing
                        return false;
                }
                byte chr = byteBuffer.get();
                if (!(chr == Constants.SP || chr == Constants.HT)) {
                    space = false;
                    byteBuffer.position(byteBuffer.position() - 1);
                }
            }
            parsingRequestLineStart = byteBuffer.position();
            parsingRequestLinePhase = 4;
        }
        if (parsingRequestLinePhase == 4) {
            // Mark the current buffer position

            int end = 0;
            //
            // Reading the URI
            //
            boolean space = false;
            while (!space) {
                // Read new bytes if needed
                if (byteBuffer.position() >= byteBuffer.limit()) {
                    if (!fill(false)) // request line parsing
                        return false;
                }
                int pos = byteBuffer.position();
                byte chr = byteBuffer.get();
                if (chr == Constants.SP || chr == Constants.HT) {
                    space = true;
                    end = pos;
                } else if (chr == Constants.CR || chr == Constants.LF) {
                    // HTTP/0.9 style request
                    parsingRequestLineEol = true;
                    space = true;
                    end = pos;
                } else if (chr == Constants.QUESTION && parsingRequestLineQPos == -1) {
                    parsingRequestLineQPos = pos;
                } else if (HttpParser.isNotRequestTarget(chr)) {
                    throw new IllegalArgumentException(sm.getString("iib.invalidRequestTarget"));
                }
            }
            if (parsingRequestLineQPos >= 0) {
                request.queryString().setBytes(byteBuffer.array(), parsingRequestLineQPos + 1,
                        end - parsingRequestLineQPos - 1);
                request.requestURI().setBytes(byteBuffer.array(), parsingRequestLineStart,
                        parsingRequestLineQPos - parsingRequestLineStart);
            } else {
                request.requestURI().setBytes(byteBuffer.array(), parsingRequestLineStart,
                        end - parsingRequestLineStart);
            }
            parsingRequestLinePhase = 5;
        }
        if (parsingRequestLinePhase == 5) {
            // Spec says single SP but also be tolerant of multiple and/or HT
            boolean space = true;
            while (space) {
                // Read new bytes if needed
                if (byteBuffer.position() >= byteBuffer.limit()) {
                    if (!fill(false)) // request line parsing
                        return false;
                }
                byte chr = byteBuffer.get();
                if (!(chr == Constants.SP || chr == Constants.HT)) {
                    space = false;
                    byteBuffer.position(byteBuffer.position() - 1);
                }
            }
            parsingRequestLineStart = byteBuffer.position();
            parsingRequestLinePhase = 6;

            // Mark the current buffer position
            end = 0;
        }
        if (parsingRequestLinePhase == 6) {
            //
            // Reading the protocol
            // Protocol is always "HTTP/" DIGIT "." DIGIT
            //
            while (!parsingRequestLineEol) {
                // Read new bytes if needed
                if (byteBuffer.position() >= byteBuffer.limit()) {
                    if (!fill(false)) // request line parsing
                        return false;
                }

                int pos = byteBuffer.position();
                byte chr = byteBuffer.get();
                if (chr == Constants.CR) {
                    end = pos;
                } else if (chr == Constants.LF) {
                    if (end == 0) {
                        end = pos;
                    }
                    parsingRequestLineEol = true;
                } else if (!HttpParser.isHttpProtocol(chr)) {
                    throw new IllegalArgumentException(sm.getString("iib.invalidHttpProtocol"));
                }
            }

            if ((end - parsingRequestLineStart) > 0) {
                request.protocol().setBytes(byteBuffer.array(), parsingRequestLineStart, end - parsingRequestLineStart);
            } else {
                request.protocol().setString("");
            }
            parsingRequestLine = false;
            parsingRequestLinePhase = 0;
            parsingRequestLineEol = false;
            parsingRequestLineStart = 0;
            return true;
        }
        throw new IllegalStateException("Invalid request line parse phase:" + parsingRequestLinePhase);
    }

 

 

 

server:
  port: 9999
  tomcat:
    max-threads: 20
    max-connections: 100
    accesslog:
      enabled: true
      pattern: '%t %a %{User-Agent}i "%r" %s (%D ms)'
    basedir: cookbook

 

[21/Jun/2019:19:54:53 +0800] 0:0:0:0:0:0:0:1 Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 Safari/537.36 "GET /swagger-ui.html?xxxxxYYYY HTTP/1.1" 200 (34 ms)

https://www.cnblogs.com/shamo89/p/8134865.html

 

 

73.6 Configure Access Logging

server.tomcat.accesslog.buffered=true # Buffer output such that it is only flushed periodically.
server.tomcat.accesslog.directory=logs # Directory in which log files are created. Can be relative to the tomcat base dir or absolute.
server.tomcat.accesslog.enabled=false # Enable access log.
server.tomcat.accesslog.file-date-format=.yyyy-MM-dd # Date format to place in log file name.
server.tomcat.accesslog.pattern=common # Format pattern for access logs.
server.tomcat.accesslog.prefix=access_log # Log file name prefix.
server.tomcat.accesslog.rename-on-rotate=false # Defer inclusion of the date stamp in the file name until rotate time.
server.tomcat.accesslog.request-attributes-enabled=false # Set request attributes for IP address, Hostname, protocol and port used for the request.
server.tomcat.accesslog.rotate=true # Enable access log rotation.
server.tomcat.accesslog.suffix=.log # Log file name suffix.

 

Access logs can be configured for Tomcat and Undertow via their respective namespaces.

For instance, the following logs access on Tomcat with a custom pattern.

server.tomcat.basedir=my-tomcat
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%t %a "%r" %s (%D ms)


%t %a "%r" %s (%D ms),日期和时间,请求来自的IP(不一定是原始IP),请求第一行,response code,响应时间(毫秒),
样例:[21/Mar/2017:00:06:40 +0800] 127.0.0.1 POST /user?v=v1.0 HTTP/1.0 200 63,这里请求来自IP就是经过本机的nginx转发的。

%t [%I] %{X-Forwarded-For}i %a %r %s (%D ms),日期和时间,线程名,原始IP,请求来自的IP(不一定是原始IP),请求第一行,response code,响应时间(毫秒),
样例:[21/Apr/2017:00:24:40 +0800][https-jsse-nio-8443-exec-7] 10.125.15.1 127.0.0.1 POST /user?v=v1.0 HTTP/1.0 200 5,这里的第一个IP是Nginx配置了X-Forwarded-For记录了原始IP,or '-' if请求头没有包含X-Forwarded-For属性 

简要介绍下上面用到的HTTP请求头X-Forwarded-For,它是一个 HTTP 扩展头部,用来表示 HTTP 请求端真实 IP,
其格式为:X-Forwarded-For: client, proxy1, proxy2,
其中的值通过一个逗号+空格把多个IP地址区分开,最左边(client)是最原始客户端的IP地址,代理服务器每成功收到一个请求,就把请求来源IP地址添加到右边。
 
负载均衡服务获取真实IP说明

负载均衡提供获取客户端真实IP地址的功能,该功能默认是开启的。

四层负载均衡(TCP协议)服务可以直接在后端ECS上获取客户端的真实IP地址,无需进行额外的配置。

七层负载均衡(HTTP/HTTPS协议)服务需要对应用服务器进行配置,然后使用X-Forwarded-For的方式获取客户端的真实IP地址。

注意:负载均衡的HTTPS监听是在负载均衡服务上的加密控制,后端仍旧使用HTTP协议,因此,在Web应用服务器配置上HTTPS和HTTP监听没有区别。
https://help.aliyun.com/document_detail/54007.html?spm=5176.doc27566.6.605.WlZhSk

 

[Note]

The default location for logs is a logs directory relative to the tomcat base dir and said directory is a temp directory by default so you may want to fix Tomcat’s base directory or use an absolute path for the logs. In the example above, the logs will be available in my-tomcat/logs relative to the working directory of the application.

Access logging for undertow can be configured in a similar fashion

server.undertow.accesslog.enabled=true
server.undertow.accesslog.pattern=%t %a "%r" %s (%D ms)

Logs are stored in a logs directory relative to the working directory of the application. This can be customized via server.undertow.accesslog.directory.

http://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/htmlsingle/#howto-configure-accesslogs

Access Logging

Access logging is performed by valves that implement org.apache.catalina.AccessLog interface.

Access Log Valve

Introduction

The Access Log Valve creates log files in the same format as those created by standard web servers. These logs can later be analyzed by standard log analysis tools to track page hit counts, user session activity, and so on. This Valve uses self-contained logic to write its log files, which can be automatically rolled over at midnight each day. (The essential requirement for access logging is to handle a large continuous stream of data with low overhead. This Valve does not use Apache Commons Logging, thus avoiding additional overhead and potentially complex configuration).

This Valve may be associated with any Catalina container (ContextHost, or Engine), and will record ALL requests processed by that container.

Some requests may be handled by Tomcat before they are passed to a container. These include redirects from /foo to /foo/ and the rejection of invalid requests. Where Tomcat can identify the Context that would have handled the request, the request/response will be logged in the AccessLog(s) associated ContextHost and Engine. Where Tomcat cannot identify the Context that would have handled the request, e.g. in cases where the URL is invalid, Tomcat will look first in the Engine, then the default Host for the Engine and finally the ROOT (or default) Context for the default Host for an AccessLog implementation. Tomcat will use the first AccessLog implementation found to log those requests that are rejected before they are passed to a container.

The output file will be placed in the directory given by the directory attribute. The name of the file is composed by concatenation of the configured prefix, timestamp and suffix. The format of the timestamp in the file name can be set using the fileDateFormat attribute. This timestamp will be omitted if the file rotation is switched off by setting rotatable to false.

Warning: If multiple AccessLogValve instances are used, they should be configured to use different output files.

If sendfile is used, the response bytes will be written asynchronously in a separate thread and the access log valve will not know how many bytes were actually written. In this case, the number of bytes that was passed to the sendfile thread for writing will be recorded in the access log valve.

Attributes

The Access Log Valve supports the following configuration attributes:

AttributeDescription
className

Java class name of the implementation to use. This MUST be set to org.apache.catalina.valves.AccessLogValve to use the default access log valve.

directory

Absolute or relative pathname of a directory in which log files created by this valve will be placed. If a relative path is specified, it is interpreted as relative to $CATALINA_BASE. If no directory attribute is specified, the default value is "logs" (relative to $CATALINA_BASE).

prefix

The prefix added to the start of each log file's name. If not specified, the default value is "access_log".

suffix

The suffix added to the end of each log file's name. If not specified, the default value is "" (a zero-length string), meaning that no suffix will be added.

fileDateFormat

Allows a customized timestamp in the access log file name. The file is rotated whenever the formatted timestamp changes. The default value is .yyyy-MM-dd. If you wish to rotate every hour, then set this value to .yyyy-MM-dd.HH. The date format will always be localized using the locale en_US.

rotatable

Flag to determine if log rotation should occur. If set to false, then this file is never rotated and fileDateFormat is ignored. Default value: true

renameOnRotate

By default for a rotatable log the active access log file name will contain the current timestamp in fileDateFormat. During rotation the file is closed and a new file with the next timestamp in the name is created and used. When setting renameOnRotate to true, the timestamp is no longer part of the active log file name. Only during rotation the file is closed and then renamed to include the timestamp. This is similar to the behavior of most log frameworks when doing time based rotation. Default value: false

pattern

A formatting layout identifying the various information fields from the request and response to be logged, or the word common or combined to select a standard format. See below for more information on configuring this attribute.

encoding

Character set used to write the log file. An empty string means to use the system default character set. Default value: use the system default character set.

locale

The locale used to format timestamps in the access log lines. Any timestamps configured using an explicit SimpleDateFormat pattern (%{xxx}t) are formatted in this locale. By default the default locale of the Java process is used. Switching the locale after the AccessLogValve is initialized is not supported. Any timestamps using the common log format (CLF) are always formatted in the locale en_US.

requestAttributesEnabled

Set to true to check for the existence of request attributes (typically set by the RemoteIpValve and similar) that should be used to override the values returned by the request for remote address, remote host, server port and protocol. If the attributes are not set, or this attribute is set to false then the values from the request will be used. If not set, the default value of false will be used.

conditionIf

Turns on conditional logging. If set, requests will be logged only if ServletRequest.getAttribute() is not null. For example, if this value is set to important, then a particular request will only be logged if ServletRequest.getAttribute("important") != null. The use of Filters is an easy way to set/unset the attribute in the ServletRequest on many different requests.

conditionUnless

Turns on conditional logging. If set, requests will be logged only if ServletRequest.getAttribute() is null. For example, if this value is set to junk, then a particular request will only be logged if ServletRequest.getAttribute("junk") == null. The use of Filters is an easy way to set/unset the attribute in the ServletRequest on many different requests.

condition

The same as conditionUnless. This attribute is provided for backwards compatibility.

buffered

Flag to determine if logging will be buffered. If set to false, then access logging will be written after each request. Default value: true

maxLogMessageBufferSize

Log message buffers are usually recycled and re-used. To prevent excessive memory usage, if a buffer grows beyond this size it will be discarded. The default is 256 characters. This should be set to larger than the typical access log message size.

resolveHosts

This attribute is no longer supported. Use the connector attribute enableLookups instead.

If you have enableLookups on the connector set to true and want to ignore it, use %a instead of %h in the value of pattern.

Values for the pattern attribute are made up of literal text strings, combined with pattern identifiers prefixed by the "%" character to cause replacement by the corresponding variable value from the current request and response. The following pattern codes are supported:

  • %a - Remote IP address
  • %A - Local IP address
  • %b - Bytes sent, excluding HTTP headers, or '-' if zero
  • %B - Bytes sent, excluding HTTP headers
  • %h - Remote host name (or IP address if enableLookups for the connector is false)
  • %H - Request protocol
  • %l - Remote logical username from identd (always returns '-')
  • %m - Request method (GET, POST, etc.)
  • %p - Local port on which this request was received. See also %{xxx}p below.
  • %q - Query string (prepended with a '?' if it exists)
  • %r - First line of the request (method and request URI)
  • %s - HTTP status code of the response
  • %S - User session ID
  • %t - Date and time, in Common Log Format
  • %u - Remote user that was authenticated (if any), else '-'
  • %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
  • %F - Time taken to commit the response, in millis
  • %I - Current request thread name (can compare later with stacktraces)

There is also support to write information incoming or outgoing headers, cookies, session or request attributes and special timestamp formats. It is modeled after the Apache HTTP Server log configuration syntax. Each of them can be used multiple times with different xxx keys:

  • %{xxx}i write value of incoming header with name xxx
  • %{xxx}o write value of outgoing header with name xxx
  • %{xxx}c write value of cookie with name xxx
  • %{xxx}r write value of ServletRequest attribute with name xxx
  • %{xxx}s write value of HttpSession attribute with name xxx
  • %{xxx}p write local (server) port (xxx==local) or remote (client) port (xxx=remote)
  • %{xxx}t write timestamp at the end of the request formatted using the enhanced SimpleDateFormat pattern xxx

All formats supported by SimpleDateFormat are allowed in %{xxx}t. In addition the following extensions have been added:

  • sec - number of seconds since the epoch
  • msec - number of milliseconds since the epoch
  • msec_frac - millisecond fraction

These formats can not be mixed with SimpleDateFormat formats in the same format token.

Furthermore one can define whether to log the timestamp for the request start time or the response finish time:

  • begin or prefix begin: chooses the request start time
  • end or prefix end: chooses the response finish time

By adding multiple %{xxx}t tokens to the pattern, one can also log both timestamps.

The shorthand pattern pattern="common" corresponds to the Common Log Format defined by '%h %l %u %t "%r" %s %b'.

The shorthand pattern pattern="combined" appends the values of the Referer and User-Agent headers, each in double quotes, to the common pattern.

When Tomcat is operating behind a reverse proxy, the client information logged by the Access Log Valve may represent the reverse proxy, the browser or some combination of the two depending on the configuration of Tomcat and the reverse proxy. For Tomcat configuration options see Proxies Support and the Proxy How-To. For reverse proxies that use mod_jk, see the generic proxy documentation. For other reverse proxies, consult their documentation.

Extended Access Log Valve

Introduction

The Extended Access Log Valve extends the Access Log Valve class, and so uses the same self-contained logging logic. This means it implements many of the same file handling attributes. The main difference to the standard AccessLogValve is thatExtendedAccessLogValve creates log files which conform to the Working Draft for the Extended Log File Format defined by the W3C.

Attributes

The Extended Access Log Valve supports all configuration attributes of the standard Access Log Valve. Only the values used for className and pattern differ.

AttributeDescription
className

Java class name of the implementation to use. This MUST be set to org.apache.catalina.valves.ExtendedAccessLogValve to use the extended access log valve.

pattern

A formatting layout identifying the various information fields from the request and response to be logged. See below for more information on configuring this attribute.

Values for the pattern attribute are made up of format tokens. Some of the tokens need an additional prefix. Possible prefixes are c for "client", s for "server", cs for "client to server", sc for "server to client" or x for "application specific". Furthermore some tokens are completed by an additional selector. See the W3C specification for more information about the format.

The following format tokens are supported:

  • bytes - Bytes sent, excluding HTTP headers, or '-' if zero
  • c-dns - Remote host name (or IP address if enableLookups for the connector is false)
  • c-ip - Remote IP address
  • cs-method - Request method (GET, POST, etc.)
  • cs-uri - Request URI
  • cs-uri-query - Query string (prepended with a '?' if it exists)
  • cs-uri-stem - Requested URL path
  • date - The date in yyyy-mm-dd format for GMT
  • s-dns - Local host name
  • s-ip - Local IP address
  • sc-status - HTTP status code of the response
  • time - Time the request was served in HH:mm:ss format for GMT
  • time-taken - Time (in seconds as floating point) taken to serve the request
  • x-threadname - Current request thread name (can compare later with stacktraces)

For any of the x-H(XXX) the following method will be called from the HttpServletRequest object:

  • x-H(authType): getAuthType
  • x-H(characterEncoding): getCharacterEncoding
  • x-H(contentLength): getContentLength
  • x-H(locale): getLocale
  • x-H(protocol): getProtocol
  • x-H(remoteUser): getRemoteUser
  • x-H(requestedSessionId): getRequestedSessionId
  • x-H(requestedSessionIdFromCookie): isRequestedSessionIdFromCookie
  • x-H(requestedSessionIdValid): isRequestedSessionIdValid
  • x-H(scheme): getScheme
  • x-H(secure): isSecure

There is also support to write information about headers cookies, context, request or session attributes and request parameters.

  • cs(XXX) for incoming request headers with name XXX
  • sc(XXX) for outgoing response headers with name XXX
  • x-A(XXX) for the servlet context attribute with name XXX
  • x-C(XXX) for the first cookie with name XXX
  • x-O(XXX) for a concatenation of all outgoing response headers with name XXX
  • x-P(XXX) for the URL encoded (using UTF-8) request parameter with name XXX
  • x-R(XXX) for the request attribute with name XXX
  • x-S(XXX) for the session attribute with name XXX

https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Access_Logging

https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html

https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/AccessLog.html

 

posted @ 2017-07-12 11:14  沧海一滴  阅读(1189)  评论(0编辑  收藏  举报