429734 Implemented the HA ProxyProtocol
This commit is contained in:
parent
6e9879cc6b
commit
4dbabd72f2
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
|
|||
* HttpTransport.completed().
|
||||
*
|
||||
*/
|
||||
public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
||||
public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, HttpParser.ProxyHandler
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(HttpChannel.class);
|
||||
private static final ThreadLocal<HttpChannel<?>> __currentChannel = new ThreadLocal<>();
|
||||
|
@ -477,6 +477,14 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort)
|
||||
{
|
||||
_request.setServerName(sAddr);
|
||||
_request.setServerPort(dPort);
|
||||
_request.setRemoteAddr(InetSocketAddress.createUnresolved(sAddr,sPort));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startRequest(HttpMethod httpMethod, String method, ByteBuffer uri, HttpVersion version)
|
||||
{
|
||||
|
@ -842,4 +850,5 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -575,6 +575,49 @@ public class BufferUtil
|
|||
return minus ? (-val) : val;
|
||||
throw new NumberFormatException(toString(buffer));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Convert buffer to an integer. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
|
||||
*
|
||||
* @param buffer
|
||||
* A buffer containing an integer in flush mode. The position is updated.
|
||||
* @return an int
|
||||
*/
|
||||
public static int takeInt(ByteBuffer buffer)
|
||||
{
|
||||
int val = 0;
|
||||
boolean started = false;
|
||||
boolean minus = false;
|
||||
int i;
|
||||
for (i = buffer.position(); i < buffer.limit(); i++)
|
||||
{
|
||||
byte b = buffer.get(i);
|
||||
if (b <= SPACE)
|
||||
{
|
||||
if (started)
|
||||
break;
|
||||
}
|
||||
else if (b >= '0' && b <= '9')
|
||||
{
|
||||
val = val * 10 + (b - '0');
|
||||
started = true;
|
||||
}
|
||||
else if (b == MINUS && !started)
|
||||
{
|
||||
minus = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (started)
|
||||
{
|
||||
buffer.position(i);
|
||||
return minus ? (-val) : val;
|
||||
}
|
||||
throw new NumberFormatException(toString(buffer));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert buffer to an long. Parses up to the first non-numeric character. If no number is found an IllegalArgumentException is thrown
|
||||
|
|
Loading…
Reference in New Issue