Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Wilkins2014-04-03 21:47:37 +0000
committerGreg Wilkins2014-04-03 21:47:37 +0000
commit4dbabd72f2ddfaf88d5893fb833481ccf60c63a9 (patch)
tree5e8e4f1ab0f780d57f19394c5289ceaa386a3308 /jetty-http
parent6e9879cc6bf115c5bb67c0feca4fe8d1d10b6cd7 (diff)
downloadorg.eclipse.jetty.project-4dbabd72f2ddfaf88d5893fb833481ccf60c63a9.tar.gz
org.eclipse.jetty.project-4dbabd72f2ddfaf88d5893fb833481ccf60c63a9.tar.xz
org.eclipse.jetty.project-4dbabd72f2ddfaf88d5893fb833481ccf60c63a9.zip
429734 Implemented the HA ProxyProtocol
Diffstat (limited to 'jetty-http')
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethod.java7
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java52
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java66
3 files changed, 118 insertions, 7 deletions
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethod.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethod.java
index ef13232125..8a2626803a 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethod.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpMethod.java
@@ -38,7 +38,8 @@ public enum HttpMethod
DELETE,
TRACE,
CONNECT,
- MOVE;
+ MOVE,
+ PROXY;
/* ------------------------------------------------------------ */
/**
@@ -48,7 +49,7 @@ public enum HttpMethod
* @param limit The first non valid index
* @return A HttpMethod if a match or null if no easy match.
*/
- public static HttpMethod lookAheadGet(byte[] bytes, int position, int limit)
+ public static HttpMethod lookAheadGet(byte[] bytes, final int position, int limit)
{
int length=limit-position;
if (length<4)
@@ -62,6 +63,8 @@ public enum HttpMethod
case 'P':
if (bytes[position+1]=='O' && bytes[position+2]=='S' && bytes[position+3]=='T' && length>=5 && bytes[position+4]==' ')
return POST;
+ if (bytes[position+1]=='R' && bytes[position+2]=='O' && bytes[position+3]=='X' && length>=6 && bytes[position+4]=='Y' && bytes[position+5]==' ')
+ return PROXY;
if (bytes[position+1]=='U' && bytes[position+2]=='T' && bytes[position+3]==' ')
return PUT;
break;
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
index 8443f67de4..b14574c0d8 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
@@ -104,6 +104,7 @@ public class HttpParser
SPACE2,
REQUEST_VERSION,
REASON,
+ PROXY,
HEADER,
HEADER_IN_NAME,
HEADER_VALUE,
@@ -403,7 +404,7 @@ public class HttpParser
* otherwise skip white space until something else to parse.
*/
private boolean quickStart(ByteBuffer buffer)
- {
+ {
if (_requestHandler!=null)
{
_method = HttpMethod.lookAheadGet(buffer);
@@ -411,6 +412,7 @@ public class HttpParser
{
_methodString = _method.asString();
buffer.position(buffer.position()+_methodString.length()+1);
+
setState(State.SPACE1);
return false;
}
@@ -655,7 +657,29 @@ public class HttpParser
version=HttpVersion.lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position()-1,buffer.arrayOffset()+buffer.limit());
else
version=HttpVersion.CACHE.getBest(buffer,0,buffer.remaining());
- if (version!=null)
+ if (version==null)
+ {
+ if (_method==HttpMethod.PROXY)
+ {
+ if (!(_requestHandler instanceof ProxyHandler))
+ throw new BadMessage();
+
+ _uri.flip();
+ String protocol=BufferUtil.toString(_uri);
+ // This is the proxy protocol, so we can assume entire first line is in buffer else 400
+ buffer.position(buffer.position()-1);
+ String sAddr = getProxyField(buffer);
+ String dAddr = getProxyField(buffer);
+ int sPort = BufferUtil.takeInt(buffer);
+ next(buffer);
+ int dPort = BufferUtil.takeInt(buffer);
+ next(buffer);
+ _state=State.START;
+ ((ProxyHandler)_requestHandler).proxied(protocol,sAddr,dAddr,sPort,dPort);
+ return false;
+ }
+ }
+ else
{
int pos = buffer.position()+version.asString().length()-1;
if (pos<buffer.limit())
@@ -715,8 +739,7 @@ public class HttpParser
if (_connectionFields==null && _version.getVersion()>=HttpVersion.HTTP_1_1.getVersion())
{
int header_cache = _handler.getHeaderCacheSize();
- if (header_cache>0)
- _connectionFields=new ArrayTernaryTrie<>(header_cache);
+ _connectionFields=new ArrayTernaryTrie<>(header_cache);
}
setState(State.HEADER);
@@ -1586,6 +1609,11 @@ public class HttpParser
public int getHeaderCacheSize();
}
+ public interface ProxyHandler
+ {
+ void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort);
+ }
+
public interface RequestHandler<T> extends HttpHandler<T>
{
/**
@@ -1618,4 +1646,20 @@ public class HttpParser
{
return _connectionFields;
}
+
+ private String getProxyField(ByteBuffer buffer)
+ {
+ _string.setLength(0);
+ _length=0;
+
+ while (buffer.hasRemaining())
+ {
+ // process each character
+ byte ch=next(buffer);
+ if (ch<=' ')
+ return _string.toString();
+ _string.append((char)ch);
+ }
+ throw new BadMessage();
+ }
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java
index 38c77af9a0..6bc6ae23e4 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java
@@ -1398,6 +1398,63 @@ public class HttpParserTest
}
+ @Test
+ public void testProxyProtocol() throws Exception
+ {
+ ByteBuffer buffer=BufferUtil
+ .toBuffer("PROXY TCP4 107.47.45.254 10.0.1.116 27689 80\015\012"
+ +"GET / HTTP/1.1\015\012"
+ +"Host: localhost \015\012"
+ +"Connection: close\015\012"+"\015\012"+"\015\012");
+
+ Handler handler=new Handler();
+ HttpParser parser=new HttpParser((HttpParser.RequestHandler)handler);
+ parseAll(parser, buffer);
+
+ assertTrue(_headerCompleted);
+ assertTrue(_messageCompleted);
+ assertEquals("GET", _methodOrVersion);
+ assertEquals("/", _uriOrStatus);
+ assertEquals("HTTP/1.1", _versionOrReason);
+ assertEquals("PROXY TCP4 107.47.45.254 10.0.1.116 27689 80", handler._proxy);
+ assertEquals("Host", _hdr[0]);
+ assertEquals("localhost", _val[0]);
+ assertEquals("Connection", _hdr[1]);
+ assertEquals("close", _val[1]);
+ assertEquals(1, _headers);
+ }
+
+ @Test
+ public void testSplitProxyHeaderParseTest() throws Exception
+ {
+ Handler handler=new Handler();
+ HttpParser parser=new HttpParser((HttpParser.RequestHandler)handler);
+
+ ByteBuffer buffer=BufferUtil.toBuffer("PROXY TCP4 207.47.45.254 10.0.1.116 27689 80\015\012");
+ parser.parseNext(buffer);
+
+ buffer=BufferUtil.toBuffer(
+ "GET / HTTP/1.1\015\012"
+ +"Host: localhost \015\012"
+ +"Connection: close\015\012"
+ +"\015\012"
+ +"\015\012");
+
+ parser.parseNext(buffer);
+ assertTrue(_headerCompleted);
+ assertTrue(_messageCompleted);
+ assertEquals("GET", _methodOrVersion);
+ assertEquals("/", _uriOrStatus);
+ assertEquals("HTTP/1.1", _versionOrReason);
+ assertEquals("PROXY TCP4 207.47.45.254 10.0.1.116 27689 80", handler._proxy);
+ assertEquals("Host", _hdr[0]);
+ assertEquals("localhost", _val[0]);
+ assertEquals("Connection", _hdr[1]);
+ assertEquals("close", _val[1]);
+ assertEquals(1, _headers);
+ }
+
+
@Before
public void init()
{
@@ -1429,9 +1486,10 @@ public class HttpParserTest
private boolean _headerCompleted;
private boolean _messageCompleted;
- private class Handler implements HttpParser.RequestHandler<ByteBuffer>, HttpParser.ResponseHandler<ByteBuffer>
+ private class Handler implements HttpParser.RequestHandler<ByteBuffer>, HttpParser.ResponseHandler<ByteBuffer>, HttpParser.ProxyHandler
{
private HttpFields fields;
+ String _proxy;
@Override
public boolean content(ByteBuffer ref)
@@ -1539,5 +1597,11 @@ public class HttpParserTest
{
return 512;
}
+
+ @Override
+ public void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort)
+ {
+ _proxy="PROXY "+protocol+" "+sAddr+" "+dAddr+" "+sPort+" "+dPort;
+ }
}
}

Back to the top