代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/jetty 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From cec50b3d2cea7bdf6b2f00d45c8554139aebbf87 Mon Sep 17 00:00:00 2001
From: Greg Wilkins <gregw@webtide.com>
Date: Wed, 8 May 2019 21:07:22 +0200
Subject: [PATCH] Issue #3630 Optimized ForwardedRequestCustomizer
Signed-off-by: Greg Wilkins <gregw@webtide.com>
---
.../eclipse/jetty/http/HostPortHttpField.java | 17 +-
.../org/eclipse/jetty/http/QuotedCSV.java | 264 +---------------
.../eclipse/jetty/http/QuotedCSVParser.java | 288 ++++++++++++++++++
.../server/ForwardedRequestCustomizer.java | 249 +++++++--------
.../ForwardedRequestCustomizerTest.java | 99 +++++-
5 files changed, 507 insertions(+), 410 deletions(-)
create mode 100644 jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSVParser.java
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java
index dc386665339..6c9f3b921e8 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HostPortHttpField.java
@@ -22,9 +22,9 @@
import org.eclipse.jetty.util.HostPort;
-
-/* ------------------------------------------------------------ */
/**
+ * A HttpField holding a preparsed Host and port number
+ * @see HostPort
*/
public class HostPortHttpField extends HttpField
{
@@ -35,7 +35,6 @@ public HostPortHttpField(String authority)
this(HttpHeader.HOST,HttpHeader.HOST.asString(),authority);
}
- /* ------------------------------------------------------------ */
protected HostPortHttpField(HttpHeader header, String name, String authority)
{
super(header,name,authority);
@@ -49,20 +48,17 @@ protected HostPortHttpField(HttpHeader header, String name, String authority)
}
}
- /* ------------------------------------------------------------ */
public HostPortHttpField(String host, int port)
{
this(new HostPort(host, port));
}
- /* ------------------------------------------------------------ */
- protected HostPortHttpField(HostPort hostport)
+ public HostPortHttpField(HostPort hostport)
{
super(HttpHeader.HOST,HttpHeader.HOST.asString(),hostport.toString());
_hostPort = hostport;
}
- /* ------------------------------------------------------------ */
/** Get the host.
* @return the host
*/
@@ -71,7 +67,6 @@ public String getHost()
return _hostPort.getHost();
}
- /* ------------------------------------------------------------ */
/** Get the port.
* @return the port
*/
@@ -80,7 +75,6 @@ public int getPort()
return _hostPort.getPort();
}
- /* ------------------------------------------------------------ */
/** Get the port.
* @param defaultPort The default port to return if no port set
* @return the port
@@ -89,4 +83,9 @@ public int getPort(int defaultPort)
{
return _hostPort.getPort(defaultPort);
}
+
+ public HostPort getHostPort()
+ {
+ return _hostPort;
+ }
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSV.java b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSV.java
index 9ca7dbeec2c..8ebc2c36307 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSV.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSV.java
@@ -22,8 +22,6 @@
import java.util.Iterator;
import java.util.List;
-import org.eclipse.jetty.util.QuotedStringTokenizer;
-
/* ------------------------------------------------------------ */
/**
* Implements a quoted comma separated list of values
@@ -32,226 +30,26 @@
* @see "https://tools.ietf.org/html/rfc7230#section-3.2.6"
* @see "https://tools.ietf.org/html/rfc7230#section-7"
*/
-public class QuotedCSV implements Iterable<String>
-{
- private enum State { VALUE, PARAM_NAME, PARAM_VALUE};
-
+public class QuotedCSV extends QuotedCSVParser implements Iterable<String>
+{
protected final List<String> _values = new ArrayList<>();
- protected final boolean _keepQuotes;
-
- /* ------------------------------------------------------------ */
+
public QuotedCSV(String... values)
{
this(true,values);
}
- /* ------------------------------------------------------------ */
public QuotedCSV(boolean keepQuotes,String... values)
{
- _keepQuotes=keepQuotes;
+ super(keepQuotes);
for (String v:values)
addValue(v);
}
-
- /* ------------------------------------------------------------ */
- /** Add and parse a value string(s)
- * @param value A value that may contain one or more Quoted CSV items.
- */
- public void addValue(String value)
- {
- if (value == null)
- return;
-
- StringBuffer buffer = new StringBuffer();
-
- int l=value.length();
- State state=State.VALUE;
- boolean quoted=false;
- boolean sloshed=false;
- int nws_length=0;
- int last_length=0;
- int value_length=-1;
- int param_name=-1;
- int param_value=-1;
-
- for (int i=0;i<=l;i++)
- {
- char c=i==l?0:value.charAt(i);
-
- // Handle quoting https://tools.ietf.org/html/rfc7230#section-3.2.6
- if (quoted && c!=0)
- {
- if (sloshed)
- sloshed=false;
- else
- {
- switch(c)
- {
- case '\\':
- sloshed=true;
- if (!_keepQuotes)
- continue;
- break;
- case '"':
- quoted=false;
- if (!_keepQuotes)
- continue;
- break;
- }
- }
-
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- // Handle common cases
- switch(c)
- {
- case ' ':
- case '\t':
- if (buffer.length()>last_length) // not leading OWS
- buffer.append(c);
- continue;
-
- case '"':
- quoted=true;
- if (_keepQuotes)
- {
- if (state==State.PARAM_VALUE && param_value<0)
- param_value=nws_length;
- buffer.append(c);
- }
- else if (state==State.PARAM_VALUE && param_value<0)
- param_value=nws_length;
- nws_length=buffer.length();
- continue;
-
- case ';':
- buffer.setLength(nws_length); // trim following OWS
- if (state==State.VALUE)
- {
- parsedValue(buffer);
- value_length=buffer.length();
- }
- else
- parsedParam(buffer,value_length,param_name,param_value);
- nws_length=buffer.length();
- param_name=param_value=-1;
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_NAME;
- continue;
-
- case ',':
- case 0:
- if (nws_length>0)
- {
- buffer.setLength(nws_length); // trim following OWS
- switch(state)
- {
- case VALUE:
- parsedValue(buffer);
- value_length=buffer.length();
- break;
- case PARAM_NAME:
- case PARAM_VALUE:
- parsedParam(buffer,value_length,param_name,param_value);
- break;
- }
- _values.add(buffer.toString());
- }
- buffer.setLength(0);
- last_length=0;
- nws_length=0;
- value_length=param_name=param_value=-1;
- state=State.VALUE;
- continue;
-
- case '=':
- switch (state)
- {
- case VALUE:
- // It wasn't really a value, it was a param name
- value_length=param_name=0;
- buffer.setLength(nws_length); // trim following OWS
- String param = buffer.toString();
- buffer.setLength(0);
- parsedValue(buffer);
- value_length=buffer.length();
- buffer.append(param);
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_VALUE;
- continue;
-
- case PARAM_NAME:
- buffer.setLength(nws_length); // trim following OWS
- buffer.append(c);
- last_length=++nws_length;
- state=State.PARAM_VALUE;
- continue;
-
- case PARAM_VALUE:
- if (param_value<0)
- param_value=nws_length;
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
- continue;
-
- default:
- {
- switch (state)
- {
- case VALUE:
- {
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- case PARAM_NAME:
- {
- if (param_name<0)
- param_name=nws_length;
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
-
- case PARAM_VALUE:
- {
- if (param_value<0)
- param_value=nws_length;
- buffer.append(c);
- nws_length=buffer.length();
- continue;
- }
- }
- }
- }
- }
- }
-
- /**
- * Called when a value has been parsed
- * @param buffer Containing the trimmed value, which may be mutated
- */
- protected void parsedValue(StringBuffer buffer)
- {
- }
- /**
- * Called when a parameter has been parsed
- * @param buffer Containing the trimmed value and all parameters, which may be mutated
- * @param valueLength The length of the value
- * @param paramName The index of the start of the parameter just parsed
- * @param paramValue The index of the start of the parameter value just parsed, or -1
- */
- protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
+ @Override
+ protected void parsedValueAndParams(StringBuffer buffer)
{
+ _values.add(buffer.toString());
}
public int size()
@@ -274,55 +72,7 @@ public boolean isEmpty()
{
return _values.iterator();
}
-
- public static String unquote(String s)
- {
- // handle trivial cases
- int l=s.length();
- if (s==null || l==0)
- return s;
-
- // Look for any quotes
- int i=0;
- for (;i<l;i++)
- {
- char c=s.charAt(i);
- if (c=='"')
- break;
- }
- if (i==l)
- return s;
- boolean quoted=true;
- boolean sloshed=false;
- StringBuffer buffer = new StringBuffer();
- buffer.append(s,0,i);
- i++;
- for (;i<l;i++)
- {
- char c=s.charAt(i);
- if (quoted)
- {
- if (sloshed)
- {
- buffer.append(c);
- sloshed=false;
- }
- else if (c=='"')
- quoted=false;
- else if (c=='\\')
- sloshed=true;
- else
- buffer.append(c);
- }
- else if (c=='"')
- quoted=true;
- else
- buffer.append(c);
- }
- return buffer.toString();
- }
-
@Override
public String toString()
{
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSVParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSVParser.java
new file mode 100644
index 00000000000..8f521db7ffb
--- /dev/null
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/QuotedCSVParser.java
@@ -0,0 +1,288 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.http;
+
+public abstract class QuotedCSVParser
+{
+ private enum State { VALUE, PARAM_NAME, PARAM_VALUE}
+
+ protected final boolean _keepQuotes;
+
+ public QuotedCSVParser(boolean keepQuotes)
+ {
+ _keepQuotes=keepQuotes;
+ }
+
+ public static String unquote(String s)
+ {
+ // handle trivial cases
+ int l=s.length();
+ if (s==null || l==0)
+ return s;
+
+ // Look for any quotes
+ int i=0;
+ for (;i<l;i++)
+ {
+ char c=s.charAt(i);
+ if (c=='"')
+ break;
+ }
+ if (i==l)
+ return s;
+
+ boolean quoted=true;
+ boolean sloshed=false;
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(s,0,i);
+ i++;
+ for (;i<l;i++)
+ {
+ char c=s.charAt(i);
+ if (quoted)
+ {
+ if (sloshed)
+ {
+ buffer.append(c);
+ sloshed=false;
+ }
+ else if (c=='"')
+ quoted=false;
+ else if (c=='\\')
+ sloshed=true;
+ else
+ buffer.append(c);
+ }
+ else if (c=='"')
+ quoted=true;
+ else
+ buffer.append(c);
+ }
+ return buffer.toString();
+ }
+
+ /** Add and parse a value string(s)
+ * @param value A value that may contain one or more Quoted CSV items.
+ */
+ public void addValue(String value)
+ {
+ if (value == null)
+ return;
+
+ StringBuffer buffer = new StringBuffer();
+
+ int l=value.length();
+ State state=State.VALUE;
+ boolean quoted=false;
+ boolean sloshed=false;
+ int nws_length=0;
+ int last_length=0;
+ int value_length=-1;
+ int param_name=-1;
+ int param_value=-1;
+
+ for (int i=0;i<=l;i++)
+ {
+ char c=i==l?0:value.charAt(i);
+
+ // Handle quoting https://tools.ietf.org/html/rfc7230#section-3.2.6
+ if (quoted && c!=0)
+ {
+ if (sloshed)
+ sloshed=false;
+ else
+ {
+ switch(c)
+ {
+ case '\\':
+ sloshed=true;
+ if (!_keepQuotes)
+ continue;
+ break;
+ case '"':
+ quoted=false;
+ if (!_keepQuotes)
+ continue;
+ break;
+ }
+ }
+
+ buffer.append(c);
+ nws_length=buffer.length();
+ continue;
+ }
+
+ // Handle common cases
+ switch(c)
+ {
+ case ' ':
+ case '\t':
+ if (buffer.length()>last_length) // not leading OWS
+ buffer.append(c);
+ continue;
+
+ case '"':
+ quoted=true;
+ if (_keepQuotes)
+ {
+ if (state==State.PARAM_VALUE && param_value<0)
+ param_value=nws_length;
+ buffer.append(c);
+ }
+ else if (state==State.PARAM_VALUE && param_value<0)
+ param_value=nws_length;
+ nws_length=buffer.length();
+ continue;
+
+ case ';':
+ buffer.setLength(nws_length); // trim following OWS
+ if (state==State.VALUE)
+ {
+ parsedValue(buffer);
+ value_length=buffer.length();
+ }
+ else
+ parsedParam(buffer,value_length,param_name,param_value);
+ nws_length=buffer.length();
+ param_name=param_value=-1;
+ buffer.append(c);
+ last_length=++nws_length;
+ state=State.PARAM_NAME;
+ continue;
+
+ case ',':
+ case 0:
+ if (nws_length>0)
+ {
+ buffer.setLength(nws_length); // trim following OWS
+ switch(state)
+ {
+ case VALUE:
+ parsedValue(buffer);
+ value_length=buffer.length();
+ break;
+ case PARAM_NAME:
+ case PARAM_VALUE:
+ parsedParam(buffer,value_length,param_name,param_value);
+ break;
+ }
+ parsedValueAndParams(buffer);
+ }
+ buffer.setLength(0);
+ last_length=0;
+ nws_length=0;
+ value_length=param_name=param_value=-1;
+ state=State.VALUE;
+ continue;
+
+ case '=':
+ switch (state)
+ {
+ case VALUE:
+ // It wasn't really a value, it was a param name
+ value_length=param_name=0;
+ buffer.setLength(nws_length); // trim following OWS
+ String param = buffer.toString();
+ buffer.setLength(0);
+ parsedValue(buffer);
+ value_length=buffer.length();
+ buffer.append(param);
+ buffer.append(c);
+ last_length=++nws_length;
+ state=State.PARAM_VALUE;
+ continue;
+
+ case PARAM_NAME:
+ buffer.setLength(nws_length); // trim following OWS
+ buffer.append(c);
+ last_length=++nws_length;
+ state=State.PARAM_VALUE;
+ continue;
+
+ case PARAM_VALUE:
+ if (param_value<0)
+ param_value=nws_length;
+ buffer.append(c);
+ nws_length=buffer.length();
+ continue;
+ }
+ continue;
+
+ default:
+ {
+ switch (state)
+ {
+ case VALUE:
+ {
+ buffer.append(c);
+ nws_length=buffer.length();
+ continue;
+ }
+
+ case PARAM_NAME:
+ {
+ if (param_name<0)
+ param_name=nws_length;
+ buffer.append(c);
+ nws_length=buffer.length();
+ continue;
+ }
+
+ case PARAM_VALUE:
+ {
+ if (param_value<0)
+ param_value=nws_length;
+ buffer.append(c);
+ nws_length=buffer.length();
+ continue;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Called when a value and it's parameters has been parsed
+ * @param buffer Containing the trimmed value and parameters
+ */
+ protected void parsedValueAndParams(StringBuffer buffer)
+ {
+ }
+
+ /**
+ * Called when a value has been parsed (prior to any parameters)
+ * @param buffer Containing the trimmed value, which may be mutated
+ */
+ protected void parsedValue(StringBuffer buffer)
+ {
+ }
+
+ /**
+ * Called when a parameter has been parsed
+ * @param buffer Containing the trimmed value and all parameters, which may be mutated
+ * @param valueLength The length of the value
+ * @param paramName The index of the start of the parameter just parsed
+ * @param paramValue The index of the start of the parameter value just parsed, or -1
+ */
+ protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
+ {
+ }
+
+}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
index be3990794ed..e098a68e635 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
@@ -30,7 +30,7 @@
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
-import org.eclipse.jetty.http.QuotedCSV;
+import org.eclipse.jetty.http.QuotedCSVParser;
import org.eclipse.jetty.server.HttpConfiguration.Customizer;
import org.eclipse.jetty.util.ArrayTrie;
import org.eclipse.jetty.util.HostPort;
@@ -42,8 +42,6 @@
import static java.lang.invoke.MethodType.methodType;
-/* ------------------------------------------------------------ */
-
/**
* Customize Requests for Proxy Forwarding.
* <p>
@@ -157,7 +155,7 @@ public String getForcedHost()
*/
public void setForcedHost(String hostAndPort)
{
- _forcedHost = new HostPortHttpField(hostAndPort);
+ _forcedHost = new HostPortHttpField(new ForcedHostPort(hostAndPort));
}
/**
@@ -377,76 +375,26 @@ public void customize(Connector connector, HttpConfiguration config, Request req
throw new RuntimeException(e);
}
- // Determine host
- if (_forcedHost != null)
- {
- // Update host header
- httpFields.put(_forcedHost);
- request.setAuthority(_forcedHost.getHost(), _forcedHost.getPort());
- }
- else if (forwarded._rfc7239 != null && forwarded._rfc7239._host != null)
- {
- HostPortHttpField auth = forwarded._rfc7239._host;
- httpFields.put(auth);
- request.setAuthority(auth.getHost(), auth.getPort());
- }
- else if (forwarded._forwardedHost != null)
- {
- HostPortHttpField auth = new HostPortHttpField(forwarded._forwardedHost);
- httpFields.put(auth);
- request.setAuthority(auth.getHost(), auth.getPort());
- }
- else if (_proxyAsAuthority)
+ if (forwarded._proto!=null)
{
- if (forwarded._rfc7239 != null && forwarded._rfc7239._by != null)
- {
- HostPortHttpField auth = forwarded._rfc7239._by;
- httpFields.put(auth);
- request.setAuthority(auth.getHost(), auth.getPort());
- }
- else if (forwarded._forwardedServer != null)
- {
- request.setAuthority(forwarded._forwardedServer, request.getServerPort());
- }
+ request.setScheme(forwarded._proto);
+ if (forwarded._proto.equalsIgnoreCase(config.getSecureScheme()))
+ request.setSecure(true);
}
- // handle remote end identifier
- if (forwarded._rfc7239 != null && forwarded._rfc7239._for != null)
- {
- request.setRemoteAddr(InetSocketAddress.createUnresolved(forwarded._rfc7239._for.getHost(), forwarded._rfc7239._for.getPort()));
- }
- else if (forwarded._forwardedFor != null)
+ if (forwarded._host!=null)
{
- int port = (forwarded._forwardedPort > 0)
- ? forwarded._forwardedPort
- : (forwarded._forwardedFor.getPort() > 0)
- ? forwarded._forwardedFor.getPort()
- : request.getRemotePort();
- request.setRemoteAddr(InetSocketAddress.createUnresolved(forwarded._forwardedFor.getHost(), port));
+ httpFields.put(new HostPortHttpField(forwarded._host));
+ request.setAuthority(forwarded._host.getHost(), forwarded._host.getPort());
}
- // handle protocol identifier
- if (forwarded._rfc7239 != null && forwarded._rfc7239._proto != null)
+ if (forwarded._for!=null)
{
- request.setScheme(forwarded._rfc7239._proto);
- if (forwarded._rfc7239._proto.equals(config.getSecureScheme()))
- request.setSecure(true);
- }
- else if (forwarded._forwardedProto != null)
- {
- request.setScheme(forwarded._forwardedProto);
- if (forwarded._forwardedProto.equals(config.getSecureScheme()))
- request.setSecure(true);
- }
- else if (forwarded._forwardedHttps != null && ("on".equalsIgnoreCase(forwarded._forwardedHttps) || "true".equalsIgnoreCase(forwarded._forwardedHttps)))
- {
- request.setScheme(HttpScheme.HTTPS.asString());
- if (HttpScheme.HTTPS.asString().equals(config.getSecureScheme()))
- request.setSecure(true);
+ int port = forwarded._for.getPort()>0 ? forwarded._for.getPort() : request.getRemotePort();
+ request.setRemoteAddr(InetSocketAddress.createUnresolved(forwarded._for.getHost(),port));
}
}
- /* ------------------------------------------------------------ */
protected String getLeftMost(String headerValue)
{
if (headerValue == null)
@@ -464,26 +412,6 @@ protected String getLeftMost(String headerValue)
return headerValue.substring(0, commaIndex).trim();
}
- protected HostPort getRemoteAddr(String headerValue)
- {
- String leftMost = getLeftMost(headerValue);
- if (leftMost == null)
- {
- return null;
- }
-
- try
- {
- return new HostPort(leftMost);
- }
- catch (Exception e)
- {
- // failed to parse in host[:port] format
- LOG.ignore(e);
- return null;
- }
- }
-
@Override
public String toString()
{
@@ -507,48 +435,6 @@ public void setHostHeader(String hostHeader)
_forcedHost = new HostPortHttpField(hostHeader);
}
- private final class RFC7239 extends QuotedCSV
- {
- HostPortHttpField _by;
- HostPortHttpField _for;
- HostPortHttpField _host;
- String _proto;
-
- private RFC7239()
- {
- super(false);
- }
-
- @Override
- protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
- {
- if (valueLength == 0 && paramValue > paramName)
- {
- String name = StringUtil.asciiToLowerCase(buffer.substring(paramName, paramValue - 1));
- String value = buffer.substring(paramValue);
- switch (name)
- {
- case "by":
- if (_by == null && !value.startsWith("_") && !"unknown".equals(value))
- _by = new HostPortHttpField(value);
- break;
- case "for":
- if (_for == null && !value.startsWith("_") && !"unknown".equals(value))
- _for = new HostPortHttpField(value);
- break;
- case "host":
- if (_host == null)
- _host = new HostPortHttpField(value);
- break;
- case "proto":
- if (_proto == null)
- _proto = value;
- break;
- }
- }
- }
- }
-
private void updateHandles()
{
int size = 0;
@@ -589,23 +475,52 @@ private void updateHandles()
}
}
- private class Forwarded
+ private static class ForcedHostPort extends HostPort
+ {
+ ForcedHostPort(String authority)
+ {
+ super(authority);
+ }
+ }
+
+ private static class XHostPort extends HostPort
+ {
+ XHostPort(String authority)
+ {
+ super(authority);
+ }
+
+ XHostPort(String host, int port)
+ {
+ super(host, port);
+ }
+ }
+
+ private static class Rfc7239HostPort extends HostPort
+ {
+ Rfc7239HostPort(String authority)
+ {
+ super(authority);
+ }
+ }
+
+ private class Forwarded extends QuotedCSVParser
{
HttpConfiguration _config;
Request _request;
- RFC7239 _rfc7239 = null;
- String _forwardedHost = null;
- String _forwardedServer = null;
- String _forwardedProto = null;
- HostPort _forwardedFor = null;
- int _forwardedPort = -1;
- String _forwardedHttps = null;
+ boolean _protoRfc7239;
+ String _proto;
+ HostPort _for;
+ HostPort _host;
public Forwarded(Request request, HttpConfiguration config)
{
+ super(false);
_request = request;
_config = config;
+ if (_forcedHost!=null)
+ _host = _forcedHost.getHostPort();
}
public void handleCipherSuite(HttpField field)
@@ -630,39 +545,87 @@ public void handleSslSessionId(HttpField field)
public void handleHost(HttpField field)
{
- _forwardedHost = getLeftMost(field.getValue());
+ if (_host==null)
+ _host = new XHostPort(getLeftMost(field.getValue()));
}
public void handleServer(HttpField field)
{
- _forwardedServer = getLeftMost(field.getValue());
+ if (_proxyAsAuthority && _host==null)
+ _host = new XHostPort(getLeftMost(field.getValue()));
}
public void handleProto(HttpField field)
{
- _forwardedProto = getLeftMost(field.getValue());
+ if (_proto==null)
+ _proto = getLeftMost(field.getValue());
}
public void handleFor(HttpField field)
{
- _forwardedFor = getRemoteAddr(field.getValue());
+ if (_for==null)
+ _for = new XHostPort(getLeftMost(field.getValue()));
+ else if (_for instanceof XHostPort && "unknown".equals(_for.getHost()))
+ _for = new XHostPort(HostPort.normalizeHost(getLeftMost(field.getValue())),_for.getPort());
}
public void handlePort(HttpField field)
{
- _forwardedPort = field.getIntValue();
+ if (_for == null)
+ _for = new XHostPort("unknown", field.getIntValue());
+ else if (_for instanceof XHostPort && _for.getPort()<=0)
+ _for = new XHostPort(HostPort.normalizeHost(_for.getHost()), field.getIntValue());
}
public void handleHttps(HttpField field)
{
- _forwardedHttps = getLeftMost(field.getValue());
+ if (_proto==null && ("on".equalsIgnoreCase(field.getValue()) || "true".equalsIgnoreCase(field.getValue())))
+ _proto = HttpScheme.HTTPS.asString();
}
public void handleRFC7239(HttpField field)
{
- if (_rfc7239 == null)
- _rfc7239 = new RFC7239();
- _rfc7239.addValue(field.getValue());
+ addValue(field.getValue());
+ }
+
+ @Override
+ protected void parsedParam(StringBuffer buffer, int valueLength, int paramName, int paramValue)
+ {
+ if (valueLength == 0 && paramValue > paramName)
+ {
+ String name = StringUtil.asciiToLowerCase(buffer.substring(paramName, paramValue - 1));
+ String value = buffer.substring(paramValue);
+ switch (name)
+ {
+ case "by":
+ if (!_proxyAsAuthority)
+ break;
+ if (value.startsWith("_") || "unknown".equals(value))
+ break;
+ if (_host == null || _host instanceof XHostPort)
+ _host = new Rfc7239HostPort(value);
+ break;
+ case "for":
+ if (value.startsWith("_") || "unknown".equals(value))
+ break;
+ if (_for == null || _for instanceof XHostPort)
+ _for = new Rfc7239HostPort(value);
+ break;
+ case "host":
+ if (value.startsWith("_") || "unknown".equals(value))
+ break;
+ if (_host == null || _host instanceof XHostPort)
+ _host = new Rfc7239HostPort(value);
+ break;
+ case "proto":
+ if (_proto == null || !_protoRfc7239)
+ {
+ _protoRfc7239 = true;
+ _proto = value;
+ }
+ break;
+ }
+ }
}
}
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java
index 0a1cecec0c2..db8a9ad64e0 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ForwardedRequestCustomizerTest.java
@@ -95,6 +95,68 @@ public void destroy() throws Exception
_server.join();
}
+ @Test
+ public void testHostIpv4() throws Exception
+ {
+ String response=_connector.getResponse(
+ "GET / HTTP/1.1\n"+
+ "Host: 1.2.3.4:2222\n"+
+ "\n");
+ assertThat(response, Matchers.containsString("200 OK"));
+ assertEquals("http",_results.poll());
+ assertEquals("1.2.3.4",_results.poll());
+ assertEquals("2222",_results.poll());
+ assertEquals("0.0.0.0",_results.poll());
+ assertEquals("0",_results.poll());
+ }
+
+ @Test
+ public void testHostIpv6() throws Exception
+ {
+ String response=_connector.getResponse(
+ "GET / HTTP/1.1\n"+
+ "Host: [::1]:2222\n"+
+ "\n");
+ assertThat(response, Matchers.containsString("200 OK"));
+ assertEquals("http",_results.poll());
+ assertEquals("[::1]",_results.poll());
+ assertEquals("2222",_results.poll());
+ assertEquals("0.0.0.0",_results.poll());
+ assertEquals("0",_results.poll());
+ }
+
+
+
+ @Test
+ public void testURIIpv4() throws Exception
+ {
+ String response=_connector.getResponse(
+ "GET http://1.2.3.4:2222/ HTTP/1.1\n"+
+ "Host: wrong\n"+
+ "\n");
+ assertThat(response, Matchers.containsString("200 OK"));
+ assertEquals("http",_results.poll());
+ assertEquals("1.2.3.4",_results.poll());
+ assertEquals("2222",_results.poll());
+ assertEquals("0.0.0.0",_results.poll());
+ assertEquals("0",_results.poll());
+ }
+
+ @Test
+ public void testURIIpv6() throws Exception
+ {
+ String response=_connector.getResponse(
+ "GET http://[::1]:2222/ HTTP/1.1\n"+
+ "Host: wrong\n"+
+ "\n");
+ assertThat(response, Matchers.containsString("200 OK"));
+ assertEquals("http",_results.poll());
+ assertEquals("[::1]",_results.poll());
+ assertEquals("2222",_results.poll());
+ assertEquals("0.0.0.0",_results.poll());
+ assertEquals("0",_results.poll());
+ }
+
@Test
public void testRFC7239_Examples_4() throws Exception
@@ -208,6 +270,7 @@ public void testFor() throws Exception
"GET / HTTP/1.1\n"+
"Host: myhost\n"+
"X-Forwarded-For: 10.9.8.7,6.5.4.3\n"+
+ "X-Forwarded-For: 8.9.8.7,7.5.4.3\n"+
"\n");
assertThat(response, Matchers.containsString("200 OK"));
assertEquals("http",_results.poll());
@@ -264,6 +327,21 @@ public void testForIpv6AndPort() throws Exception
assertEquals("80",_results.poll());
assertEquals("[1:2:3:4:5:6:7:8]",_results.poll());
assertEquals("2222",_results.poll());
+
+ response=_connector.getResponse(
+ "GET / HTTP/1.1\n"+
+ "Host: myhost\n"+
+ "X-Forwarded-Port: 2222\n"+
+ "X-Forwarded-For: 1:2:3:4:5:6:7:8\n"+
+ "X-Forwarded-For: 7:7:7:7:7:7:7:7\n"+
+ "X-Forwarded-Port: 3333\n"+
+ "\n");
+ assertThat(response, Matchers.containsString("200 OK"));
+ assertEquals("http",_results.poll());
+ assertEquals("myhost",_results.poll());
+ assertEquals("80",_results.poll());
+ assertEquals("[1:2:3:4:5:6:7:8]",_results.poll());
+ assertEquals("2222",_results.poll());
}
@Test
@@ -355,7 +433,26 @@ public void testSslCertificate() throws Exception
assertTrue(_wasSecure.get());
assertEquals("0123456789abcdef",_sslCertificate.get());
}
-
+
+
+ @Test
+ public void testMixed() throws Exception
+ {
+ String response = _connector.getResponse(
+ "GET / HTTP/1.1\n" +
+ "Host: myhost\n" +
+ "X-Forwarded-For: 11.9.8.7:1111,8.5.4.3:2222\n" +
+ "X-Forwarded-Port: 3333\n" +
+ "Forwarded: for=192.0.2.43,for=198.51.100.17;by=203.0.113.60;proto=http;host=example.com\n"+
+ "X-Forwarded-For: 11.9.8.7:1111,8.5.4.3:2222\n" +
+ "\n");
+
+ assertEquals("http",_results.poll());
+ assertEquals("example.com",_results.poll());
+ assertEquals("80",_results.poll());
+ assertEquals("192.0.2.43",_results.poll());
+ assertEquals("0",_results.poll());
+ }
interface RequestTester
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。