diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java index ed45cb75809..031ad11e8d0 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java @@ -56,8 +56,7 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async setCurrentConnection(this); // don't check for idle while dispatched (unless blocking IO is done). - if(!_request.isAsyncCompleted()) - _asyncEndp.setCheckForIdle(false); + _asyncEndp.setCheckForIdle(false); // While progress and the connection has not changed @@ -140,14 +139,14 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async setCurrentConnection(null); // If we are not suspended - if (!_request.isAsyncStarted()) + if (!_request.getAsyncContinuation().isAsyncStarted()) { // return buffers _parser.returnBuffers(); _generator.returnBuffers(); } - if (_request.isAsyncCompleted() || _request.isAsyncInitial()) + if (_request.getAsyncContinuation().isComplete() || _request.getAsyncContinuation().isInitial()) { _asyncEndp.setCheckForIdle(true); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java index 4c16fec280b..4fc8c5934d5 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java @@ -308,10 +308,11 @@ public class Request implements HttpServletRequest } } + /* ------------------------------------------------------------ */ public AsyncContext getAsyncContext() { - if (_async.isInitial() && !isAsyncStarted()) + if (_async.isInitial() && !_async.isAsyncStarted()) throw new IllegalStateException(_async.getStatusString()); return _async; } @@ -1260,34 +1261,16 @@ public class Request implements HttpServletRequest } /* ------------------------------------------------------------ */ - public boolean isAsyncStarted() + public boolean isHandled() { - return _async.isAsyncStarted(); + return _handled; } - - /* ------------------------------------------------------------ */ - public boolean isAsyncInitial() - { - return _async.isInitial(); - } - - /* ------------------------------------------------------------ */ - public boolean isAsyncCompleted() - { - return _async.isComplete(); - } - + /* ------------------------------------------------------------ */ public boolean isAsyncSupported() { return _asyncSupported; } - - /* ------------------------------------------------------------ */ - public boolean isHandled() - { - return _handled; - } /* ------------------------------------------------------------ */ /* diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java index 9a5aeb0e1f1..c3479cb4d4a 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java @@ -13,9 +13,13 @@ package org.eclipse.jetty.server; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.net.Socket; -import java.net.SocketException; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.session.SessionHandler; @@ -34,7 +38,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest startServer(connector); } - @Test(expected=SocketException.class) + @Test public void testIdleTimeoutAfterSuspend() throws Exception { SuspendHandler _handler = new SuspendHandler(); @@ -46,10 +50,10 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest _handler.setSuspendFor(100); _handler.setResumeAfter(25); - process(null); + assertTrue(process(null).toUpperCase().contains("RESUMED")); } - @Test(expected=SocketException.class) + @Test public void testIdleTimeoutAfterTimeout() throws Exception { SuspendHandler _handler = new SuspendHandler(); @@ -60,11 +64,11 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest _server.start(); _handler.setSuspendFor(50); - System.out.println(process(null)); + assertTrue(process(null).toUpperCase().contains("TIMEOUT")); } - @Test(expected=SocketException.class) - public void testIdleTimeoutAfterComplete() throws Exception + @Test + public void testIdleTimeoutAfterComplete() throws Exception { SuspendHandler _handler = new SuspendHandler(); _server.stop(); @@ -75,11 +79,10 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest _handler.setSuspendFor(100); _handler.setCompleteAfter(25); - System.out.println(process(null)); + assertTrue(process(null).toUpperCase().contains("COMPLETED")); } - // TODO: remove code duplication to LocalAsyncContextTest.java - private synchronized String process(String content) throws Exception + private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException { String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n" + "Connection: close\r\n"; @@ -90,15 +93,16 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest return getResponse(request); } - protected String getResponse(String request) throws Exception + private String getResponse(String request) throws UnsupportedEncodingException, IOException, InterruptedException { SelectChannelConnector connector = (SelectChannelConnector)_connector; Socket socket = new Socket((String)null,connector.getLocalPort()); socket.getOutputStream().write(request.getBytes("UTF-8")); InputStream inputStream = socket.getInputStream(); + String response = IO.toString(inputStream); Thread.sleep(500); - socket.getOutputStream().write(10); - return IO.toString(inputStream); + assertEquals("Socket should be closed and return -1 on reading",-1,socket.getInputStream().read()); + return response; } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java new file mode 100644 index 00000000000..f5ea64c3bd1 --- /dev/null +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java @@ -0,0 +1,153 @@ +package org.eclipse.jetty.server; + +import java.io.IOException; +import java.io.InputStream; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.server.handler.HandlerWrapper; + +class SuspendHandler extends HandlerWrapper +{ + private int _read; + private long _suspendFor=-1; + private long _resumeAfter=-1; + private long _completeAfter=-1; + + public SuspendHandler() + { + } + + public int getRead() + { + return _read; + } + + public void setRead(int read) + { + _read = read; + } + + public long getSuspendFor() + { + return _suspendFor; + } + + public void setSuspendFor(long suspendFor) + { + _suspendFor = suspendFor; + } + + public long getResumeAfter() + { + return _resumeAfter; + } + + public void setResumeAfter(long resumeAfter) + { + _resumeAfter = resumeAfter; + } + + public long getCompleteAfter() + { + return _completeAfter; + } + + public void setCompleteAfter(long completeAfter) + { + _completeAfter = completeAfter; + } + + @Override + public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException + { + if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType())) + { + if (_read>0) + { + byte[] buf=new byte[_read]; + request.getInputStream().read(buf); + } + else if (_read<0) + { + InputStream in = request.getInputStream(); + int b=in.read(); + while(b!=-1) + b=in.read(); + } + + final AsyncContext asyncContext = baseRequest.startAsync(); + asyncContext.addContinuationListener(LocalAsyncContextTest.__asyncListener); + if (_suspendFor>0) + asyncContext.setTimeout(_suspendFor); + + if (_completeAfter>0) + { + new Thread() { + @Override + public void run() + { + try + { + Thread.sleep(_completeAfter); + response.getOutputStream().print("COMPLETED"); + response.setStatus(200); + baseRequest.setHandled(true); + asyncContext.complete(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + }.start(); + } + else if (_completeAfter==0) + { + response.getOutputStream().print("COMPLETED"); + response.setStatus(200); + baseRequest.setHandled(true); + asyncContext.complete(); + } + + if (_resumeAfter>0) + { + new Thread() { + @Override + public void run() + { + try + { + Thread.sleep(_resumeAfter); + if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null) + asyncContext.dispatch(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + }.start(); + } + else if (_resumeAfter==0) + { + asyncContext.dispatch(); + } + } + else if (request.getAttribute("TIMEOUT")!=null) + { + response.setStatus(200); + response.getOutputStream().print("TIMEOUT"); + baseRequest.setHandled(true); + } + else + { + response.setStatus(200); + response.getOutputStream().print("RESUMED"); + baseRequest.setHandled(true); + } + } + +} \ No newline at end of file