Issue #525 Looping on malformed request

Improved onBadMessage handling so that it better handles ISE thrown when a bad message is detected while dispatched to the servlet.
This commit is contained in:
Greg Wilkins 2016-04-27 18:57:15 +10:00
parent a1eab9d9a4
commit 695b63fc78
3 changed files with 65 additions and 19 deletions

View File

@ -1426,7 +1426,7 @@ public class HttpParser
break;
default:
setState(State.CLOSE);
_handler.badMessage(400,null);
_handler.badMessage(400,"Bad Message "+e.toString());
}
}
catch(Exception|Error e)

View File

@ -643,9 +643,21 @@ public class HttpChannel implements Runnable, HttpOutput.Interceptor
if (status < 400 || status > 599)
status = HttpStatus.BAD_REQUEST_400;
Action action;
try
{
if (_state.handling()==Action.DISPATCH)
action=_state.handling();
}
catch(IllegalStateException e)
{
// The bad message cannot be handled in the current state, so throw
// to hopefull somebody that can handle
throw new BadMessageException(status,reason);
}
try
{
if (action==Action.DISPATCH)
{
ByteBuffer content=null;
HttpFields fields=new HttpFields();

View File

@ -21,9 +21,12 @@ package org.eclipse.jetty.servlet;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -32,12 +35,12 @@ import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StacklessLogging;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@Ignore
public class PostServletTest
{
private static final Logger LOG = Log.getLogger(PostServletTest.class);
@ -48,19 +51,21 @@ public class PostServletTest
{
try
{
request.getInputStream().read();
byte[] buffer = new byte[4096];
ServletInputStream in = request.getInputStream();
int l = in.read(buffer);
while (l>0)
{
// System.err.println("READ: "+new String(buffer,0,l,StandardCharsets.ISO_8859_1));
l = in.read(buffer);
}
}
catch (IOException e0)
{
try
{
// this read-call should fail immediately
request.getInputStream().read();
}
catch (IOException e1)
{
LOG.warn(e1);
}
LOG.warn(e0);
}
}
}
@ -90,6 +95,29 @@ public class PostServletTest
this.server.stop();
}
@Test
public void testGoodPost() throws Exception
{
StringBuilder req = new StringBuilder();
req.append("POST /post HTTP/1.1\r\n");
req.append("Host: localhost\r\n");
req.append("Connection: close\r\n");
req.append("Transfer-Encoding: chunked\r\n");
req.append("\r\n");
req.append("6\r\n");
req.append("Hello ");
req.append("\r\n");
req.append("6\r\n");
req.append("World\n");
req.append("\r\n");
req.append("0\r\n");
req.append("\r\n");
String resp = connector.getResponses(req.toString());
assertThat("resp", resp, containsString("HTTP/1.1 200 OK"));
}
@Test
public void testBadPost() throws Exception
{
@ -99,13 +127,19 @@ public class PostServletTest
req.append("Connection: close\r\n");
req.append("Transfer-Encoding: chunked\r\n");
req.append("\r\n");
req.append("x\r\n"); // intentionally bad (not a valid chunked char here)
req.append("6\r\n");
req.append("Hello ");
req.append("\r\n");
req.append("x\r\n");
req.append("World\n");
req.append("\r\n");
req.append("0\r\n");
req.append("\r\n");
String resp = connector.getResponses(req.toString());
TimeUnit.MINUTES.sleep(4);
assertThat("resp", resp, containsString("HTTP/1.1 400 Bad Request"));
try (StacklessLogging scope = new StacklessLogging(ServletHandler.class))
{
String resp = connector.getResponses(req.toString());
assertThat("resp", resp, containsString("HTTP/1.1 500 "));
}
}
}