diff options
author | Greg Wilkins | 2014-04-03 21:47:37 +0000 |
---|---|---|
committer | Greg Wilkins | 2014-04-03 21:47:37 +0000 |
commit | 4dbabd72f2ddfaf88d5893fb833481ccf60c63a9 (patch) | |
tree | 5e8e4f1ab0f780d57f19394c5289ceaa386a3308 /jetty-http | |
parent | 6e9879cc6bf115c5bb67c0feca4fe8d1d10b6cd7 (diff) | |
download | org.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')
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; + } } } |