420033 AsyncContext.onTimeout exceptions passed to onError

Conflicts:
	jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java
	jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java
	jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
This commit is contained in:
Greg Wilkins 2013-10-24 15:30:35 +11:00
parent d38233c52d
commit ac3787b167
3 changed files with 88 additions and 8 deletions

View File

@ -274,10 +274,19 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
if (_request.getHttpChannelState().isExpired())
{
_request.setDispatcherType(DispatcherType.ERROR);
Throwable ex=_state.getAsyncContextEvent().getThrowable();
String reason="Async Timeout";
if (ex!=null)
{
reason="Async Exception";
_request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,ex);
}
_request.setAttribute(RequestDispatcher.ERROR_STATUS_CODE,new Integer(500));
_request.setAttribute(RequestDispatcher.ERROR_MESSAGE,"Async Timeout");
_request.setAttribute(RequestDispatcher.ERROR_MESSAGE,reason);
_request.setAttribute(RequestDispatcher.ERROR_REQUEST_URI,_request.getRequestURI());
_response.setStatusWithReason(500,"Async Timeout");
_response.setStatusWithReason(500,reason);
ErrorHandler eh = _state.getContextHandler().getErrorHandler();
if (eh instanceof ErrorHandler.ErrorPageMapper)

View File

@ -348,7 +348,7 @@ public class HttpChannelState
protected void expired()
{
final List<AsyncListener> aListeners;
AsyncEvent event;
AsyncContextEvent event;
synchronized (this)
{
switch(_state)
@ -374,7 +374,10 @@ public class HttpChannelState
}
catch(Exception e)
{
LOG.warn(e);
LOG.debug(e);
event.setThrowable(e);
_channel.getRequest().setAttribute(RequestDispatcher.ERROR_EXCEPTION,e);
break;
}
}
}

View File

@ -28,7 +28,10 @@ import java.io.IOException;
import java.io.StringReader;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@ -76,6 +79,7 @@ public class AsyncContextTest
_contextHandler.addServlet(new ServletHolder(new ForwardingServlet()),"/forward");
_contextHandler.addServlet(new ServletHolder(new AsyncDispatchingServlet()),"/dispatchingServlet");
_contextHandler.addServlet(new ServletHolder(new ExpireServlet()),"/expire/*");
_contextHandler.addServlet(new ServletHolder(new BadExpireServlet()),"/badexpire/*");
_contextHandler.addServlet(new ServletHolder(new ErrorServlet()),"/error/*");
ErrorPageErrorHandler error_handler = new ErrorPageErrorHandler();
@ -287,8 +291,11 @@ public class AsyncContextTest
@Test
public void testExpire() throws Exception
{
String request = "GET /ctx/expire HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Connection: close\r\n" + "\r\n";
String request = "GET /ctx/expire HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Connection: close\r\n" +
"\r\n";
String responseString = _connector.getResponses(request);
BufferedReader br = new BufferedReader(new StringReader(responseString));
@ -302,6 +309,27 @@ public class AsyncContextTest
Assert.assertEquals("error servlet","ERROR: /error",br.readLine());
}
@Test
public void testBadExpire() throws Exception
{
String request = "GET /ctx/badexpire HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Connection: close\r\n" +
"\r\n";
String responseString = _connector.getResponses(request);
BufferedReader br = new BufferedReader(new StringReader(responseString));
assertEquals("HTTP/1.1 500 Async Exception",br.readLine());
br.readLine();// connection close
br.readLine();// server
br.readLine();// empty
Assert.assertEquals("error servlet","ERROR: /error",br.readLine());
Assert.assertEquals("error servlet","EXCEPTION: java.io.IOException: TEST",br.readLine());
}
private class DispatchingRunnable implements Runnable
{
private AsyncContext asyncContext;
@ -337,6 +365,8 @@ public class AsyncContextTest
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
response.getOutputStream().print("ERROR: " + request.getServletPath() + "\n");
if (request.getAttribute(RequestDispatcher.ERROR_EXCEPTION)!=null)
response.getOutputStream().print("EXCEPTION: " + request.getAttribute(RequestDispatcher.ERROR_EXCEPTION) + "\n");
}
}
@ -355,6 +385,44 @@ public class AsyncContextTest
}
}
private class BadExpireServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
if (request.getDispatcherType()==DispatcherType.REQUEST)
{
AsyncContext asyncContext = request.startAsync();
asyncContext.addListener(new AsyncListener()
{
@Override
public void onTimeout(AsyncEvent event) throws IOException
{
throw new IOException("TEST");
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException
{
}
@Override
public void onError(AsyncEvent event) throws IOException
{
}
@Override
public void onComplete(AsyncEvent event) throws IOException
{
}
});
asyncContext.setTimeout(100);
}
}
}
private class TestServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;