Skip to content

Commit

Permalink
Added optional X-Request-Id to RemoteIpFilter
Browse files Browse the repository at this point in the history
  • Loading branch information
isapir committed Oct 2, 2024
1 parent 217aca2 commit 5f24286
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
57 changes: 57 additions & 0 deletions java/org/apache/catalina/filters/RemoteIpFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,14 @@
* <td>x-forwarded-for</td>
* </tr>
* <tr>
* <td>requestIdHeader</td>
* <td>Name of the Http Header read by this servlet filter that holds a request ID passed by a proxy or the requesting
* client</td>
* <td>RequestIdHeader</td>
* <td>Compliant http header name</td>
* <td>x-request-id</td>
* </tr>
* <tr>
* <td>internalProxies</td>
* <td>Regular expression that matches the IP addresses of internal proxies. If they appear in the
* <code>remoteIpHeader</code> value, they will be trusted and will not appear in the <code>proxiesHeader</code>
Expand Down Expand Up @@ -210,6 +218,10 @@
* &lt;param-name&gt;protocolHeader&lt;/param-name&gt;
* &lt;param-value&gt;x-forwarded-proto&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;init-param&gt;
* &lt;param-name&gt;requestIdHeader&lt;/param-name&gt;
* &lt;param-value&gt;x-request-id&lt;/param-value&gt;
* &lt;/init-param&gt;
* &lt;/filter&gt;
*
* &lt;filter-mapping&gt;
Expand Down Expand Up @@ -476,6 +488,8 @@ public static class XForwardedRequest extends HttpServletRequestWrapper {

protected int serverPort;

protected String requestId;

public XForwardedRequest(HttpServletRequest request) {
super(request);
this.localName = request.getLocalName();
Expand Down Expand Up @@ -568,6 +582,15 @@ public String getRemoteHost() {
return this.remoteHost;
}

@Override
public String getRequestId() {
if (this.requestId != null) {
return this.requestId;
}

return super.getRequest().getRequestId();
}

@Override
public String getScheme() {
return scheme;
Expand Down Expand Up @@ -617,6 +640,10 @@ public void setRemoteHost(String remoteHost) {
this.remoteHost = remoteHost;
}

public void setRequestId(String requestId) {
this.requestId = requestId;
}

public void setScheme(String scheme) {
this.scheme = scheme;
}
Expand Down Expand Up @@ -667,6 +694,8 @@ public StringBuffer getRequestURL() {

protected static final String REMOTE_IP_HEADER_PARAMETER = "remoteIpHeader";

protected static final String REQUEST_ID_HEADER_PARAMETER = "requestIdHeader";

protected static final String TRUSTED_PROXIES_PARAMETER = "trustedProxies";

protected static final String ENABLE_LOOKUPS_PARAMETER = "enableLookups";
Expand Down Expand Up @@ -717,6 +746,11 @@ public StringBuffer getRequestURL() {
*/
private String remoteIpHeader = "X-Forwarded-For";

/**
* @see #setRequestIdHeader(String)
*/
private String requestIdHeader = "";

/**
* @see #setRequestAttributesEnabled(boolean)
*/
Expand Down Expand Up @@ -843,6 +877,14 @@ public void doFilter(HttpServletRequest request, HttpServletResponse response, F
}
}
}

if (!requestIdHeader.isEmpty()) {
String requestIdHeaderValue = request.getHeader(requestIdHeader);
if (requestIdHeaderValue != null) {
xRequest.setRequestId(requestIdHeaderValue);
}
}

request.setAttribute(Globals.REQUEST_FORWARDED_ATTRIBUTE, Boolean.TRUE);

if (log.isTraceEnabled()) {
Expand Down Expand Up @@ -1016,6 +1058,10 @@ public void init() throws ServletException {
setRemoteIpHeader(getInitParameter(REMOTE_IP_HEADER_PARAMETER));
}

if (getInitParameter(REQUEST_ID_HEADER_PARAMETER) != null) {
setRequestIdHeader(getInitParameter(REQUEST_ID_HEADER_PARAMETER));
}

if (getInitParameter(TRUSTED_PROXIES_PARAMETER) != null) {
setTrustedProxies(getInitParameter(TRUSTED_PROXIES_PARAMETER));
}
Expand Down Expand Up @@ -1221,6 +1267,17 @@ public void setRemoteIpHeader(String remoteIpHeader) {
this.remoteIpHeader = remoteIpHeader;
}

/**
* <p>Name of the http header from which the request id is extracted.</p>
*
* <p>Request id propagation is disabled by default. Set a value, e.g. <code>X-Request-Id</code>, to enable it.</p>
*
* @param requestIdHeader The header name
*/
public void setRequestIdHeader(String requestIdHeader) {
this.requestIdHeader = requestIdHeader;
}

/**
* Should this filter set request attributes for IP address, Hostname, protocol and port used for the request? This
* are typically used in conjunction with an {@link AccessLog} which will otherwise log the original values. Default
Expand Down
11 changes: 11 additions & 0 deletions webapps/docs/config/filter.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,10 @@ FINE: Request "/docs/config/manager.html" with response status "200"
<param-name>protocolHeader</param-name>
<param-value>x-forwarded-proto</param-value>
</init-param>
<init-param>
<param-name>requestIdHeader</param-name>
<param-value>x-request-id</param-value>
</init-param>
</filter>]]></source>
<p>Request values:</p>
<table class="defaultTable">
Expand Down Expand Up @@ -1685,6 +1689,13 @@ FINE: Request "/docs/config/manager.html" with response status "200"
specified, the default of <code>x-forwarded-for</code> is used.</p>
</attribute>

<attribute name="requestIdHeader" required="false">
<p>Name of the HTTP Header read by this valve that holds request ID
if passed by the Proxy server or requesting client. Request ID propagation
is disabled by default, but can be enabled by setting this attribute,
e.g. to <code>x-request-id</code>.</p>
</attribute>

<attribute name="internalProxies" required="false">
<p>Regular expression (using <code>java.util.regex</code>) that a
proxy&apos;s IP address must match to be considered an internal proxy.
Expand Down

2 comments on commit 5f24286

@michael-o
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I noticed is that one cannot access this ID at all via {{AccessLogValve}}. Maybe we should extend it as well?

@isapir
Copy link
Member Author

@isapir isapir commented on 5f24286 Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michael-o Yeah, I was thinking the same. Maybe extract XForwardedRequest so that it's not an inner class of the RemoteIpFilter and then we can use it for both the Filter and the Valve.

It's weird but it was difficult for me to find your message. I remembered seeing an email notification so I looked for it. The PR is now at #758 so it would be easier to communicate in the PR thread rather than here.

Please sign in to comment.