387919: throw EOFException on early eof from client on http requests
This commit is contained in:
parent
2bd6cf2ebf
commit
9173751438
|
@ -129,6 +129,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
private boolean _head = false;
|
||||
private boolean _host = false;
|
||||
private boolean _delayedHandling=false;
|
||||
private boolean _earlyEOF = false;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static AbstractHttpConnection getCurrentConnection()
|
||||
|
@ -394,6 +395,12 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
return _generator.isCommitted();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isEarlyEOF()
|
||||
{
|
||||
return _earlyEOF;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void reset()
|
||||
{
|
||||
|
@ -407,6 +414,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
_response.recycle();
|
||||
_uri.clear();
|
||||
_writer=null;
|
||||
_earlyEOF = false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -443,7 +451,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
{
|
||||
_uri.getPort();
|
||||
String path = null;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
path = _uri.getDecodedPath();
|
||||
|
@ -454,7 +462,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
LOG.ignore(e);
|
||||
path = _uri.getDecodedPath(StringUtil.__ISO_8859_1);
|
||||
}
|
||||
|
||||
|
||||
info=URIUtil.canonicalPath(path);
|
||||
if (info==null && !_request.getMethod().equals(HttpMethods.CONNECT))
|
||||
{
|
||||
|
@ -719,6 +727,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
_requests);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void startRequest(Buffer method, Buffer uri, Buffer version) throws IOException
|
||||
{
|
||||
uri=uri.asImmutableBuffer();
|
||||
|
@ -778,6 +787,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void parsedHeader(Buffer name, Buffer value) throws IOException
|
||||
{
|
||||
int ho = HttpHeaders.CACHE.getOrdinal(name);
|
||||
|
@ -839,6 +849,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
_requestFields.add(name, value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void headerComplete() throws IOException
|
||||
{
|
||||
_requests++;
|
||||
|
@ -909,6 +920,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
_delayedHandling=true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void content(Buffer buffer) throws IOException
|
||||
{
|
||||
if (_delayedHandling)
|
||||
|
@ -918,6 +930,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void messageComplete(long contentLength) throws IOException
|
||||
{
|
||||
if (_delayedHandling)
|
||||
|
@ -927,6 +940,12 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void earlyEOF()
|
||||
{
|
||||
_earlyEOF = true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -996,6 +1015,18 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Bad request!: "+version+" "+status+" "+reason);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.jetty.server.server.HttpParser.EventHandler#earlyEOF()
|
||||
*/
|
||||
@Override
|
||||
public void earlyEOF()
|
||||
{
|
||||
AbstractHttpConnection.this.earlyEOF();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -24,12 +24,13 @@ import javax.servlet.ServletInputStream;
|
|||
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.EofException;
|
||||
|
||||
public class HttpInput extends ServletInputStream
|
||||
{
|
||||
protected final AbstractHttpConnection _connection;
|
||||
protected final HttpParser _parser;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public HttpInput(AbstractHttpConnection connection)
|
||||
{
|
||||
|
@ -44,11 +45,9 @@ public class HttpInput extends ServletInputStream
|
|||
@Override
|
||||
public int read() throws IOException
|
||||
{
|
||||
int c=-1;
|
||||
Buffer content=_parser.blockForContent(_connection.getMaxIdleTime());
|
||||
if (content!=null)
|
||||
c= 0xff & content.get();
|
||||
return c;
|
||||
byte[] bytes = new byte[1];
|
||||
int read = read(bytes, 0, 1);
|
||||
return read < 0 ? -1 : 0xff & bytes[0];
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -62,6 +61,8 @@ public class HttpInput extends ServletInputStream
|
|||
Buffer content=_parser.blockForContent(_connection.getMaxIdleTime());
|
||||
if (content!=null)
|
||||
l= content.get(b, off, len);
|
||||
else if (_connection.isEarlyEOF())
|
||||
throw new EofException("early EOF");
|
||||
return l;
|
||||
}
|
||||
|
||||
|
@ -71,8 +72,4 @@ public class HttpInput extends ServletInputStream
|
|||
{
|
||||
return _parser.available();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -30,15 +30,16 @@ import java.net.SocketException;
|
|||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.Exchanger;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletInputStream;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.EofException;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
|
@ -50,10 +51,11 @@ import org.junit.Test;
|
|||
import org.junit.matchers.JUnitMatchers;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -148,8 +150,55 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
client.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testInterruptedRequest() throws Exception
|
||||
{
|
||||
final AtomicBoolean fourBytesRead = new AtomicBoolean(false);
|
||||
final AtomicBoolean earlyEOFException = new AtomicBoolean(false);
|
||||
configureServer(new AbstractHandler()
|
||||
{
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
int contentLength = request.getContentLength();
|
||||
ServletInputStream inputStream = request.getInputStream();
|
||||
for (int i = 0; i < contentLength; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
inputStream.read();
|
||||
}
|
||||
catch (EofException e)
|
||||
{
|
||||
earlyEOFException.set(true);
|
||||
throw e;
|
||||
}
|
||||
if (i == 3)
|
||||
fourBytesRead.set(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
StringBuffer request = new StringBuffer("GET / HTTP/1.0\n");
|
||||
request.append("Host: localhost\n");
|
||||
request.append("Content-length: 6\n\n");
|
||||
request.append("foo");
|
||||
|
||||
Socket client = newSocket(HOST, _connector.getLocalPort());
|
||||
OutputStream os = client.getOutputStream();
|
||||
|
||||
os.write(request.toString().getBytes());
|
||||
os.flush();
|
||||
client.shutdownOutput();
|
||||
String response = readResponse(client);
|
||||
client.close();
|
||||
|
||||
// assertThat("response contains 200 OK", response.contains(" 500 "), is(true)); //TODO: check with gregw,
|
||||
// currently returns 200
|
||||
assertThat("The 4th byte (-1) has not been passed to the handler", fourBytesRead.get(), is(false));
|
||||
assertThat("EofException has been caught", earlyEOFException.get(), is(true));
|
||||
}
|
||||
|
||||
/*
|
||||
* Feed the server the entire request at once.
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
//
|
||||
|
||||
package org.eclipse.jetty.server.ssl;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
@ -26,13 +24,11 @@ import java.net.Socket;
|
|||
import java.security.KeyStore;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
|
||||
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.nio.SslConnection;
|
||||
|
@ -41,8 +37,10 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* HttpServer Tester.
|
||||
|
@ -166,6 +164,12 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
@Ignore("Override and ignore this test as SSLSocket.shutdownOutput() is not supported, " +
|
||||
"but shutdownOutput() is needed by the test.")
|
||||
public void testInterruptedRequest(){}
|
||||
|
||||
@Override
|
||||
@Ignore
|
||||
public void testAvailable() throws Exception
|
||||
|
|
|
@ -75,6 +75,12 @@ public class SslSocketServerTest extends HttpServerTestBase
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
@Ignore("Override and ignore this test as SSLSocket.shutdownOutput() is not supported, " +
|
||||
"but shutdownOutput() is needed by the test.")
|
||||
public void testInterruptedRequest(){}
|
||||
|
||||
@Override
|
||||
@Test
|
||||
public void testFlush() throws Exception
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
# Setup default logging implementation for during testing
|
||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
org.eclipse.jetty.server.LEVEL=INFO
|
Loading…
Reference in New Issue