Hi Konstantin, please see below:
You can configure a Valve for a specific web application by placing it
into Context configuration for that specific web application (usually
that is the "/META-INF/context.xml" configuration file). [1]
[1]
http://tomcat.apache.org/tomcat-9.0-doc/config/context.html#Defining_a_context
You are correct. I realized this after my original response. We actually
already use per-context AccessLogValves.
2. If I understand correctly, the null value from
request.getRemoteAddr() means that the client connection has already
been closed.
Tomcat cannot do much at that point, unless the information has not
already been requested (and thus cached) when the connection was still
alive. (The recent changes to the AccessLogValve are just that: to
request the value earlier.)
It is useless to process a request if the connection has already been closed.
We request getRemoteAddr() several times during servlet processing (for
Geolocation, proxy and carrier detection among other purposes), as well
as in top-of-the-chain servlet filters.
If the connection has been closed, it must be because of some Tomcat
issue. This never happened with earlier Tomcar versions (we started this
project many years ago with 6.x). Plus, the issue is only present in a
small number of cases on HTTP/2, but not regular HTTPS nor plain HTTP.
Why do you say that the null value is an invalid one? I do not see
such words in the specification.
I disagree. There cannot be a TCP/IP, HTTP, HTTPS, HTTP/2 or HTTP/3-QUIC
connection without an originating IP, so it makes no sense to return
NULL under any circumstances.
Furthermore, the spec Javadoc for getRemoteAddr() states "Returns: a
String containing the IP address of the client that sent the request"
Contrast this to getRemoteUser() for instance, which states: "Returns: a
String specifying the login of the user making this request, *or null if
the user login is not known*"
If NULL were a valid return value, it would be explicitly mentioned.
3. Just as a note (I would not recommend it for your specific use case)
One known way to detect a closed connection is to trigger parameter
parsing and look whether an error flag (implemented as an attribute of
a Request) was set by it. See the implementation of
org.apache.catalina.filters.FailedRequestFilter for an example.
As a workaround, since we only have a very small number of requests that
trigger this, we have implemented a filter that discards those requests
and returns HTTP 400 "Bad Request", until the issue is resolved.
4. Do you run with the following configuration setting turned on?
org.apache.catalina.connector.RECYCLE_FACADES=true
We do not use this option, so we must be running with the default="false"
See
https://cwiki.apache.org/confluence/x/yColBg#TroubleshootingandDiagnostics-TroubleshootingunexpectedResponsestateproblems
Thanks, I'll read through this.
*Manuel Dominguez Sarmiento*