Skip to content

Commit

Permalink
Fixes #842 - Implement RFC7239 support in Proxy and Middleman.
Browse files Browse the repository at this point in the history
Updated ee10/ee11 AbstractProxyServlet to use the `Forwarded` header rather than the now deprecated `X-Forwarded-For` headers.

Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
  • Loading branch information
sbordet committed Oct 10, 2024
1 parent e4e0bbf commit e9b4624
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ private Set<String> parseList(String list)
for (String host : hosts)
{
host = host.trim();
if (host.length() == 0)
if (host.isEmpty())
continue;
result.add(host);
}
Expand Down Expand Up @@ -538,7 +538,7 @@ protected Set<String> findConnectionHeaders(HttpServletRequest clientRequest)
protected void addProxyHeaders(HttpServletRequest clientRequest, Request proxyRequest)
{
addViaHeader(proxyRequest);
addXForwardedHeaders(clientRequest, proxyRequest);
addForwardedHeader(clientRequest, proxyRequest);
}

/**
Expand Down Expand Up @@ -580,23 +580,43 @@ protected void addViaHeader(HttpServletRequest clientRequest, Request proxyReque
.flatMap(field -> Stream.of(field.getValues()))
.filter(value -> !StringUtil.isBlank(value))
.collect(Collectors.joining(separator));
if (newValue.length() > 0)
if (!newValue.isEmpty())
newValue += separator;
newValue += viaHeaderValue;
return new HttpField(HttpHeader.VIA, newValue);
}));
}

protected void addXForwardedHeaders(HttpServletRequest clientRequest, Request proxyRequest)
{
proxyRequest.headers(headers -> headers.add(HttpHeader.X_FORWARDED_FOR, clientRequest.getRemoteAddr()));
proxyRequest.headers(headers -> headers.add(HttpHeader.X_FORWARDED_PROTO, clientRequest.getScheme()));
String hostHeader = clientRequest.getHeader(HttpHeader.HOST.asString());
if (hostHeader != null)
proxyRequest.headers(headers -> headers.add(HttpHeader.X_FORWARDED_HOST, hostHeader));
String localName = clientRequest.getLocalName();
if (localName != null)
proxyRequest.headers(headers -> headers.add(HttpHeader.X_FORWARDED_SERVER, localName));
protected void addForwardedHeader(HttpServletRequest clientRequest, Request proxyRequest)
{
String byAttr = clientRequest.getLocalAddr();
String forAttr = clientRequest.getRemoteAddr();
String hostAttr = clientRequest.getHeader(HttpHeader.HOST.asString());
String scheme = clientRequest.getScheme();
String protoAttr = scheme == null ? (clientRequest.isSecure() ? "https" : "http") : scheme;
String forwardedValue = "by=%s;for=%s;host=%s;proto=%s".formatted(
HttpField.PARAMETER_TOKENIZER.quote(byAttr),
HttpField.PARAMETER_TOKENIZER.quote(forAttr),
HttpField.PARAMETER_TOKENIZER.quote(hostAttr),
protoAttr
);
proxyRequest.headers(headers -> headers.computeField(HttpHeader.FORWARDED, (header, fields) ->
{
String newValue;
if (fields == null || fields.isEmpty())
{
newValue = forwardedValue;
}
else
{
String separator = ", ";
newValue = fields.stream()
.flatMap(field -> field.getValueList().stream())
.collect(Collectors.joining(separator));
newValue += separator + forwardedValue;
}
return new HttpField(HttpHeader.FORWARDED, newValue);
}));
}

protected void sendProxyRequest(HttpServletRequest clientRequest, HttpServletResponse proxyResponse, Request proxyRequest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -572,17 +572,17 @@ public void testProxyXForwardedHostHeaderIsPresent(Class<? extends ProxyServlet>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
PrintWriter writer = resp.getWriter();
writer.write(req.getHeader("X-Forwarded-Host"));
writer.write(req.getHeader(HttpHeader.FORWARDED.asString()));
writer.flush();
}
});
startProxy(proxyServletClass);
startClient();

ContentResponse response = client.GET("http://localhost:" + serverConnector.getLocalPort());
assertThat("Response expected to contain content of X-Forwarded-Host Header from the request",
assertThat("Response expected to contain content of Forwarded header from the request",
response.getContentAsString(),
equalTo("localhost:" + serverConnector.getLocalPort()));
containsString("localhost:" + serverConnector.getLocalPort()));
}

@ParameterizedTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ private Set<String> parseList(String list)
for (String host : hosts)
{
host = host.trim();
if (host.length() == 0)
if (host.isEmpty())
continue;
result.add(host);
}
Expand Down Expand Up @@ -538,7 +538,7 @@ protected Set<String> findConnectionHeaders(HttpServletRequest clientRequest)
protected void addProxyHeaders(HttpServletRequest clientRequest, Request proxyRequest)
{
addViaHeader(proxyRequest);
addXForwardedHeaders(clientRequest, proxyRequest);
addForwardedHeader(clientRequest, proxyRequest);
}

/**
Expand Down Expand Up @@ -580,23 +580,43 @@ protected void addViaHeader(HttpServletRequest clientRequest, Request proxyReque
.flatMap(field -> Stream.of(field.getValues()))
.filter(value -> !StringUtil.isBlank(value))
.collect(Collectors.joining(separator));
if (newValue.length() > 0)
if (!newValue.isEmpty())
newValue += separator;
newValue += viaHeaderValue;
return new HttpField(HttpHeader.VIA, newValue);
}));
}

protected void addXForwardedHeaders(HttpServletRequest clientRequest, Request proxyRequest)
{
proxyRequest.headers(headers -> headers.add(HttpHeader.X_FORWARDED_FOR, clientRequest.getRemoteAddr()));
proxyRequest.headers(headers -> headers.add(HttpHeader.X_FORWARDED_PROTO, clientRequest.getScheme()));
String hostHeader = clientRequest.getHeader(HttpHeader.HOST.asString());
if (hostHeader != null)
proxyRequest.headers(headers -> headers.add(HttpHeader.X_FORWARDED_HOST, hostHeader));
String localName = clientRequest.getLocalName();
if (localName != null)
proxyRequest.headers(headers -> headers.add(HttpHeader.X_FORWARDED_SERVER, localName));
protected void addForwardedHeader(HttpServletRequest clientRequest, Request proxyRequest)
{
String byAttr = clientRequest.getLocalAddr();
String forAttr = clientRequest.getRemoteAddr();
String hostAttr = clientRequest.getHeader(HttpHeader.HOST.asString());
String scheme = clientRequest.getScheme();
String protoAttr = scheme == null ? (clientRequest.isSecure() ? "https" : "http") : scheme;
String forwardedValue = "by=%s;for=%s;host=%s;proto=%s".formatted(
HttpField.PARAMETER_TOKENIZER.quote(byAttr),
HttpField.PARAMETER_TOKENIZER.quote(forAttr),
HttpField.PARAMETER_TOKENIZER.quote(hostAttr),
protoAttr
);
proxyRequest.headers(headers -> headers.computeField(HttpHeader.FORWARDED, (header, fields) ->
{
String newValue;
if (fields == null || fields.isEmpty())
{
newValue = forwardedValue;
}
else
{
String separator = ", ";
newValue = fields.stream()
.flatMap(field -> field.getValueList().stream())
.collect(Collectors.joining(separator));
newValue += separator + forwardedValue;
}
return new HttpField(HttpHeader.FORWARDED, newValue);
}));
}

protected void sendProxyRequest(HttpServletRequest clientRequest, HttpServletResponse proxyResponse, Request proxyRequest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -572,17 +572,17 @@ public void testProxyXForwardedHostHeaderIsPresent(Class<? extends ProxyServlet>
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
{
PrintWriter writer = resp.getWriter();
writer.write(req.getHeader("X-Forwarded-Host"));
writer.write(req.getHeader(HttpHeader.FORWARDED.asString()));
writer.flush();
}
});
startProxy(proxyServletClass);
startClient();

ContentResponse response = client.GET("http://localhost:" + serverConnector.getLocalPort());
assertThat("Response expected to contain content of X-Forwarded-Host Header from the request",
assertThat("Response expected to contain content of Forwarded header from the request",
response.getContentAsString(),
equalTo("localhost:" + serverConnector.getLocalPort()));
containsString("localhost:" + serverConnector.getLocalPort()));
}

@ParameterizedTest
Expand Down

0 comments on commit e9b4624

Please sign in to comment.