372115: set pathInContext for suspend with request

This commit is contained in:
Greg Wilkins 2012-02-28 13:25:45 +11:00
parent 8e1b863deb
commit 763bd6b190
3 changed files with 151 additions and 40 deletions

View File

@ -19,14 +19,17 @@ import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationThrowable;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Timeout;
@ -291,7 +294,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#suspend(long)
*/
protected void suspend(final ServletContext context,
private void doSuspend(final ServletContext context,
final ServletRequest request,
final ServletResponse response)
{
@ -307,10 +310,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
if (_event==null || request!=_event.getRequest() || response != _event.getResponse() || context != _event.getServletContext())
_event=new AsyncEventState(context,request,response);
else
{
_event._dispatchContext=null;
_event._pathInContext=null;
}
_state=__ASYNCSTARTED;
break;
@ -319,7 +319,6 @@ public class AsyncContinuation implements AsyncContext, Continuation
throw new IllegalStateException(this.getStatusString());
}
}
}
/* ------------------------------------------------------------ */
@ -810,6 +809,26 @@ public class AsyncContinuation implements AsyncContext, Continuation
dispatch();
}
/* ------------------------------------------------------------ */
protected void suspend(final ServletContext context,
final ServletRequest request,
final ServletResponse response)
{
synchronized (this)
{
HttpServletRequest r = (HttpServletRequest)request;
System.err.printf("Suspend %s %s | %s %s%n",r.getServletPath(),r.getPathInfo(),r.getAttribute(Dispatcher.FORWARD_SERVLET_PATH), r.getAttribute(Dispatcher.FORWARD_PATH_INFO));
doSuspend(context,request,response);
if ( request instanceof HttpServletRequest)
_event._pathInContext=URIUtil.addPaths(((HttpServletRequest)request).getServletPath(),((HttpServletRequest)request).getPathInfo());
else
_event._pathInContext=null;
}
}
/* ------------------------------------------------------------ */
/**
* @see Continuation#suspend()
@ -817,7 +836,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
public void suspend(ServletResponse response)
{
_responseWrapped=!(response instanceof Response);
AsyncContinuation.this.suspend(_connection.getRequest().getServletContext(),_connection.getRequest(),response);
doSuspend(_connection.getRequest().getServletContext(),_connection.getRequest(),response);
}
/* ------------------------------------------------------------ */
@ -827,7 +846,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
public void suspend()
{
_responseWrapped=false;
AsyncContinuation.this.suspend(_connection.getRequest().getServletContext(),_connection.getRequest(),_connection.getResponse());
doSuspend(_connection.getRequest().getServletContext(),_connection.getRequest(),_connection.getResponse());
}
/* ------------------------------------------------------------ */
@ -915,10 +934,10 @@ public class AsyncContinuation implements AsyncContext, Continuation
if (uri!=null)
{
r.setAttribute(AsyncContext.ASYNC_REQUEST_URI,uri);
r.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,(String)r.getAttribute(Dispatcher.FORWARD_CONTEXT_PATH));
r.setAttribute(AsyncContext.ASYNC_SERVLET_PATH,(String)r.getAttribute(Dispatcher.FORWARD_SERVLET_PATH));
r.setAttribute(AsyncContext.ASYNC_PATH_INFO,(String)r.getAttribute(Dispatcher.FORWARD_PATH_INFO));
r.setAttribute(AsyncContext.ASYNC_QUERY_STRING,(String)r.getAttribute(Dispatcher.FORWARD_QUERY_STRING));
r.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,r.getAttribute(Dispatcher.FORWARD_CONTEXT_PATH));
r.setAttribute(AsyncContext.ASYNC_SERVLET_PATH,r.getAttribute(Dispatcher.FORWARD_SERVLET_PATH));
r.setAttribute(AsyncContext.ASYNC_PATH_INFO,r.getAttribute(Dispatcher.FORWARD_PATH_INFO));
r.setAttribute(AsyncContext.ASYNC_QUERY_STRING,r.getAttribute(Dispatcher.FORWARD_QUERY_STRING));
}
else
{

View File

@ -46,7 +46,6 @@ import javax.servlet.http.HttpSession;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpMethods;
@ -1885,7 +1884,7 @@ public class Request implements HttpServletRequest
{
if (!_asyncSupported)
throw new IllegalStateException("!asyncSupported");
_async.suspend(_context,this,_connection._response);
_async.suspend();
return _async;
}

View File

@ -8,21 +8,23 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.*;
import junit.framework.Assert;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.server.AsyncContext;
import org.eclipse.jetty.server.AsyncContinuation;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
/**
@ -40,13 +42,15 @@ public class AsyncContextTest
@Before
public void setUp() throws Exception
{
_connector.setMaxIdleTime(30000);
_connector.setMaxIdleTime(3000000);
_server.setConnectors(new Connector[]
{ _connector });
_contextHandler.setContextPath("/");
_contextHandler.addServlet(new ServletHolder(new TestServlet()),"/servletPath");
_contextHandler.addServlet(new ServletHolder(new TestServlet2()),"/servletPath2");
_contextHandler.addServlet(new ServletHolder(new ForwardingServlet()),"/forward");
_contextHandler.addServlet(new ServletHolder(new AsyncDispatchingServlet()),"/dispatchingServlet");
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[]
@ -57,7 +61,6 @@ public class AsyncContextTest
}
@Test
//Ignore ("test fails without a patch")
public void testSimpleAsyncContext() throws Exception
{
String request = "GET /servletPath HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
@ -78,7 +81,6 @@ public class AsyncContextTest
}
@Test
//Ignore ("test fails without a patch")
public void testDispatchAsyncContext() throws Exception
{
String request = "GET /servletPath?dispatch=true HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
@ -103,7 +105,6 @@ public class AsyncContextTest
}
@Test
//Ignore ("test fails without a patch")
public void testSimpleWithContextAsyncContext() throws Exception
{
_contextHandler.setContextPath("/foo");
@ -126,7 +127,6 @@ public class AsyncContextTest
}
@Test
//Ignore ("test fails without a patch")
public void testDispatchWithContextAsyncContext() throws Exception
{
_contextHandler.setContextPath("/foo");
@ -153,8 +153,99 @@ public class AsyncContextTest
Assert.assertEquals("context path attr is correct","async:run:attr:contextPath:/foo", br.readLine());
Assert.assertEquals("request uri attr is correct","async:run:attr:requestURI:/foo/servletPath", br.readLine());
}
@Test
public void testDispatch() throws Exception
{
String request = "GET /forward 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 200 OK",br.readLine());
br.readLine();// connection close
br.readLine();// server
br.readLine();// empty
assertThat("!ForwardingServlet",br.readLine(),equalTo("Dispatched back to ForwardingServlet"));
}
@Test
public void testDispatchRequestResponse() throws Exception
{
String request = "GET /forward?dispatchRequestResponse=true 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 200 OK",br.readLine());
br.readLine();// connection close
br.readLine();// server
br.readLine();// empty
assertThat("!AsyncDispatchingServlet",br.readLine(),equalTo("Dispatched back to AsyncDispatchingServlet"));
}
private class ForwardingServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
{
if (((Request)request).getDispatcherType() == DispatcherType.ASYNC)
{
response.getOutputStream().print("Dispatched back to ForwardingServlet");
}
else
{
request.getRequestDispatcher("/dispatchingServlet").forward(request,response);
}
}
}
private class AsyncDispatchingServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, final HttpServletResponse response) throws ServletException, IOException
{
Request request = (Request)req;
if (request.getDispatcherType() == DispatcherType.ASYNC)
{
response.getOutputStream().print("Dispatched back to AsyncDispatchingServlet");
}
else
{
final AsyncContext asyncContext;
if (request.getParameter("dispatchRequestResponse") != null)
asyncContext = request.startAsync(request,response);
else
asyncContext = request.startAsync();
new Thread(new DispatchingRunnable(asyncContext)).start();
}
}
}
private class DispatchingRunnable implements Runnable
{
private AsyncContext asyncContext;
public DispatchingRunnable(AsyncContext asyncContext)
{
this.asyncContext = asyncContext;
}
public void run()
{
asyncContext.dispatch();
}
}
@After
public void tearDown() throws Exception
{
@ -166,15 +257,16 @@ public class AsyncContextTest
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
AsyncContinuation continuation = (AsyncContinuation) ContinuationSupport.getContinuation(request);
AsyncContinuation continuation = (AsyncContinuation)ContinuationSupport.getContinuation(request);
if (request.getParameter("dispatch") != null)
{
continuation.suspend();
continuation.dispatch("/servletPath2");
//AsyncContext asyncContext = request.startAsync(request,response);
// AsyncContext asyncContext = request.startAsync(request,response);
}
else
{
@ -182,13 +274,13 @@ public class AsyncContextTest
continuation.suspend();
//AsyncContext asyncContext = request.startAsync(request,response);
// AsyncContext asyncContext = request.startAsync(request,response);
response.getOutputStream().print("doGet:async:getServletPath:" + ((HttpServletRequest)continuation.getRequest()).getServletPath() + "\n");
Runnable runable = new AsyncRunnable(continuation);
new Thread(runable).start();
//asyncContext.start(new AsyncRunnable(asyncContext));
// asyncContext.start(new AsyncRunnable(asyncContext));
}
return;
@ -199,24 +291,25 @@ public class AsyncContextTest
{
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
AsyncContinuation continuation = (AsyncContinuation) ContinuationSupport.getContinuation(request);
AsyncContinuation continuation = (AsyncContinuation)ContinuationSupport.getContinuation(request);
response.getOutputStream().print("doGet:getServletPath:" + request.getServletPath() + "\n");
continuation.suspend();
//AsyncContext asyncContext = request.startAsync(request, response);
// AsyncContext asyncContext = request.startAsync(request, response);
response.getOutputStream().print("doGet:async:getServletPath:" + ((HttpServletRequest)continuation.getRequest()).getServletPath() + "\n");
Runnable runable = new AsyncRunnable(continuation);
new Thread(runable).start();
//asyncContext.start(new AsyncRunnable(asyncContext));
// asyncContext.start(new AsyncRunnable(asyncContext));
return;
}
}
private class AsyncRunnable implements Runnable
{
private AsyncContinuation _continuation;
@ -228,22 +321,22 @@ public class AsyncContextTest
public void run()
{
HttpServletRequest req = (HttpServletRequest)_continuation.getRequest();
HttpServletRequest req = (HttpServletRequest)_continuation.getRequest();
try
{
_continuation.getResponse().getOutputStream().print("async:run:attr:servletPath:" + req.getAttribute(AsyncContext.ASYNC_SERVLET_PATH) + "\n");
_continuation.getResponse().getOutputStream().print("async:run:attr:pathInfo:" + req.getAttribute(AsyncContext.ASYNC_PATH_INFO) + "\n");
_continuation.getResponse().getOutputStream().print("async:run:attr:queryString:" + req.getAttribute(AsyncContext.ASYNC_QUERY_STRING) + "\n");
_continuation.getResponse().getOutputStream().print("async:run:attr:contextPath:" + req.getAttribute(AsyncContext.ASYNC_CONTEXT_PATH) + "\n");
_continuation.getResponse().getOutputStream().print("async:run:attr:requestURI:" + req.getAttribute(AsyncContext.ASYNC_REQUEST_URI) + "\n");
_continuation.getResponse().getOutputStream().print("async:run:attr:pathInfo:" + req.getAttribute(AsyncContext.ASYNC_PATH_INFO) + "\n");
_continuation.getResponse().getOutputStream().print("async:run:attr:queryString:" + req.getAttribute(AsyncContext.ASYNC_QUERY_STRING) + "\n");
_continuation.getResponse().getOutputStream().print("async:run:attr:contextPath:" + req.getAttribute(AsyncContext.ASYNC_CONTEXT_PATH) + "\n");
_continuation.getResponse().getOutputStream().print("async:run:attr:requestURI:" + req.getAttribute(AsyncContext.ASYNC_REQUEST_URI) + "\n");
}
catch (IOException e)
{
e.printStackTrace();
}
_continuation.complete();
_continuation.complete();
}
}