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 98516f73faf..6de3357e44a 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
@@ -632,28 +632,8 @@ 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 (_method==HttpMethod.PROXY)
- {
- if (!(_requestHandler instanceof ProxyHandler))
- throw new BadMessageException();
-
- String protocol=_uri.toString();
- // 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
+
+ if (version!=null)
{
int pos = buffer.position()+version.asString().length()-1;
if (pos
\ncontentType="+request.getContentType()+"\n\n"); writer.write("
\nencoding="+request.getCharacterEncoding()+"\n\n"); writer.write("
\nservername="+request.getServerName()+"\n\n"); + writer.write("
\nlocal="+request.getLocalAddr()+":"+request.getLocalPort()+"\n\n"); + writer.write("
\nremote="+request.getRemoteAddr()+":"+request.getRemotePort()+"\n\n"); writer.write("
"); writer.write(request.getMethod()+" "+request.getRequestURI()+" "+request.getProtocol()+"\n"); Enumerationheaders = request.getHeaderNames(); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyConnectionTest.java new file mode 100644 index 00000000000..1593372fdbd --- /dev/null +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ProxyConnectionTest.java @@ -0,0 +1,171 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 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.server; + +import org.eclipse.jetty.server.handler.ErrorHandler; +import org.hamcrest.Matchers; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** + * + */ +public class ProxyConnectionTest +{ + private Server _server; + private LocalConnector _connector; + + @Before + public void init() throws Exception + { + _server = new Server(); + + + HttpConnectionFactory http = new HttpConnectionFactory(); + http.getHttpConfiguration().setRequestHeaderSize(1024); + http.getHttpConfiguration().setResponseHeaderSize(1024); + + ProxyConnectionFactory proxy = new ProxyConnectionFactory(http.getProtocol()); + + _connector = new LocalConnector(_server,null,null,null,1,proxy,http); + _connector.setIdleTimeout(1000); + _server.addConnector(_connector); + _server.setHandler(new DumpHandler()); + ErrorHandler eh=new ErrorHandler(); + eh.setServer(_server); + _server.addBean(eh); + _server.start(); + } + + @After + public void destroy() throws Exception + { + _server.stop(); + _server.join(); + } + + @Test + public void testSimple() throws Exception + { + String response=_connector.getResponses("PROXY TCP 1.2.3.4 5.6.7.8 111 222\r\n"+ + "GET /path HTTP/1.1\n"+ + "Host: server:80\n"+ + "Connection: close\n"+ + "\n"); + + Assert.assertThat(response,Matchers.containsString("HTTP/1.1 200")); + Assert.assertThat(response,Matchers.containsString("pathInfo=/path")); + Assert.assertThat(response,Matchers.containsString("local=5.6.7.8:222")); + Assert.assertThat(response,Matchers.containsString("remote=1.2.3.4:111")); + } + + @Test + public void testIPv6() throws Exception + { + String response=_connector.getResponses("PROXY UNKNOWN eeee:eeee:eeee:eeee:eeee:eeee:eeee:eeee ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff 65535 65535\r\n"+ + "GET /path HTTP/1.1\n"+ + "Host: server:80\n"+ + "Connection: close\n"+ + "\n"); + + Assert.assertThat(response,Matchers.containsString("HTTP/1.1 200")); + Assert.assertThat(response,Matchers.containsString("pathInfo=/path")); + Assert.assertThat(response,Matchers.containsString("remote=eeee:eeee:eeee:eeee:eeee:eeee:eeee:eeee:65535")); + Assert.assertThat(response,Matchers.containsString("local=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:65535")); + } + + @Test + public void testTooLong() throws Exception + { + String response=_connector.getResponses("PROXY TOOLONG!!! eeee:eeee:eeee:eeee:0000:0000:0000:0000 ffff:ffff:ffff:ffff:0000:0000:0000:0000 65535 65535\r\n"+ + "GET /path HTTP/1.1\n"+ + "Host: server:80\n"+ + "Connection: close\n"+ + "\n"); + + Assert.assertThat(response,Matchers.equalTo("")); + } + + @Test + public void testNotComplete() throws Exception + { + _connector.setIdleTimeout(100); + String response=_connector.getResponses("PROXY TIMEOUT"); + Assert.assertThat(response,Matchers.equalTo("")); + } + + @Test + public void testBadChar() throws Exception + { + String response=_connector.getResponses("PROXY\tTCP 1.2.3.4 5.6.7.8 111 222\r\n"+ + "GET /path HTTP/1.1\n"+ + "Host: server:80\n"+ + "Connection: close\n"+ + "\n"); + Assert.assertThat(response,Matchers.equalTo("")); + } + + @Test + public void testBadCRLF() throws Exception + { + String response=_connector.getResponses("PROXY TCP 1.2.3.4 5.6.7.8 111 222\r \n"+ + "GET /path HTTP/1.1\n"+ + "Host: server:80\n"+ + "Connection: close\n"+ + "\n"); + Assert.assertThat(response,Matchers.equalTo("")); + } + + @Test + public void testBadPort() throws Exception + { + String response=_connector.getResponses("PROXY TCP 1.2.3.4 5.6.7.8 9999999999999 222\r\n"+ + "GET /path HTTP/1.1\n"+ + "Host: server:80\n"+ + "Connection: close\n"+ + "\n"); + Assert.assertThat(response,Matchers.equalTo("")); + } + + @Test + public void testMissingField() throws Exception + { + String response=_connector.getResponses("PROXY TCP 1.2.3.4 5.6.7.8 222\r\n"+ + "GET /path HTTP/1.1\n"+ + "Host: server:80\n"+ + "Connection: close\n"+ + "\n"); + Assert.assertThat(response,Matchers.equalTo("")); + } + + @Test + public void testHTTP() throws Exception + { + String response=_connector.getResponses( + "GET /path HTTP/1.1\n"+ + "Host: server:80\n"+ + "Connection: close\n"+ + "\n"); + Assert.assertThat(response,Matchers.equalTo("")); + } +} + + diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java index 5af0db73a0c..d1a358a0283 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java @@ -516,10 +516,12 @@ public class BufferUtil } /* ------------------------------------------------------------ */ - /** Convert a partial buffer to a String - * @param buffer The buffer to convert in flush mode. The buffer is unchanged + /** Convert a partial buffer to a String. + * + * @param position The position in the buffer to start the string from + * @param length The length of the buffer * @param charset The {@link Charset} to use to convert the bytes - * @return The buffer as a string. + * @return The buffer as a string. */ public static String toString(ByteBuffer buffer, int position, int length, Charset charset) { @@ -547,12 +549,30 @@ public class BufferUtil * @return an int */ public static int toInt(ByteBuffer buffer) + { + return toInt(buffer,buffer.position(),buffer.remaining()); + } + + /* ------------------------------------------------------------ */ + /** + * 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 not changed. + * @return an int + */ + public static int toInt(ByteBuffer buffer, int position, int length) { int val = 0; boolean started = false; boolean minus = false; - for (int i = buffer.position(); i < buffer.limit(); i++) + int limit = position+length; + + if (length<=0) + throw new NumberFormatException(toString(buffer,position,length,StandardCharsets.UTF_8)); + + for (int i = position; i < limit; i++) { byte b = buffer.get(i); if (b <= SPACE)