[Bug #371635] and [Bug #371649] add missing attributes (non-optimal) and resolve async flow issue with scoping
This commit is contained in:
parent
af07ce4b6c
commit
a90c3201e8
|
@ -370,6 +370,9 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
baseRequest.setAttribute(AsyncContext.ASYNC_QUERY_STRING,baseRequest.getQueryString());
|
||||
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,state.getSuspendedContext().getContextPath());
|
||||
|
||||
// Part of #371649 reset here since we skip it in finally
|
||||
baseRequest.setServletPath(null);
|
||||
|
||||
final String contextPath=state.getServletContext().getContextPath();
|
||||
HttpURI uri = new HttpURI(URIUtil.addPaths(contextPath,path));
|
||||
|
|
|
@ -971,6 +971,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
}
|
||||
finally
|
||||
{
|
||||
|
||||
if (old_context != _scontext)
|
||||
{
|
||||
// reset the classloader
|
||||
|
@ -983,8 +984,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
baseRequest.setContext(old_context);
|
||||
__context.set(old_context);
|
||||
baseRequest.setContextPath(old_context_path);
|
||||
baseRequest.setServletPath(old_servlet_path);
|
||||
baseRequest.setPathInfo(old_path_info);
|
||||
|
||||
// #371649 if we have started async then we need to protect this state
|
||||
if (!baseRequest.getAsyncContinuation().isAsyncStarted())
|
||||
{
|
||||
baseRequest.setServletPath(old_servlet_path);
|
||||
baseRequest.setPathInfo(old_path_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.eclipse.jetty.io.RuntimeIOException;
|
|||
import org.eclipse.jetty.security.IdentityService;
|
||||
import org.eclipse.jetty.security.SecurityHandler;
|
||||
import org.eclipse.jetty.server.AbstractHttpConnection;
|
||||
import org.eclipse.jetty.server.AsyncContext;
|
||||
import org.eclipse.jetty.server.Dispatcher;
|
||||
import org.eclipse.jetty.server.DispatcherType;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
|
@ -351,7 +352,7 @@ public class ServletHandler extends ScopedHandler
|
|||
// Get the base requests
|
||||
final String old_servlet_path=baseRequest.getServletPath();
|
||||
final String old_path_info=baseRequest.getPathInfo();
|
||||
|
||||
|
||||
DispatcherType type = baseRequest.getDispatcherType();
|
||||
|
||||
ServletHolder servlet_holder=null;
|
||||
|
@ -376,7 +377,7 @@ public class ServletHandler extends ScopedHandler
|
|||
baseRequest.setAttribute(Dispatcher.INCLUDE_PATH_INFO, path_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
baseRequest.setServletPath(servlet_path);
|
||||
baseRequest.setPathInfo(path_info);
|
||||
}
|
||||
|
@ -397,6 +398,21 @@ public class ServletHandler extends ScopedHandler
|
|||
old_scope=baseRequest.getUserIdentityScope();
|
||||
baseRequest.setUserIdentityScope(servlet_holder);
|
||||
|
||||
/*
|
||||
* this is an interim solution for Bug 371635
|
||||
*
|
||||
* these will always be set now, when they ought to only be set on the dispatch
|
||||
*/
|
||||
if ( baseRequest.getAttribute(AsyncContext.ASYNC_SERVLET_PATH) == null )
|
||||
{
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_SERVLET_PATH,baseRequest.getServletPath());
|
||||
}
|
||||
|
||||
if ( baseRequest.getAttribute(AsyncContext.ASYNC_PATH_INFO) == null )
|
||||
{
|
||||
baseRequest.setAttribute(AsyncContext.ASYNC_PATH_INFO,baseRequest.getPathInfo());
|
||||
}
|
||||
|
||||
// start manual inline of nextScope(target,baseRequest,request,response);
|
||||
if (never())
|
||||
nextScope(target,baseRequest,request,response);
|
||||
|
@ -410,13 +426,18 @@ public class ServletHandler extends ScopedHandler
|
|||
}
|
||||
finally
|
||||
{
|
||||
if (old_scope!=null)
|
||||
baseRequest.setUserIdentityScope(old_scope);
|
||||
|
||||
if (!(DispatcherType.INCLUDE.equals(type)))
|
||||
// #371649 if we have started async then we need to protect this state
|
||||
if (!baseRequest.getAsyncContinuation().isAsyncStarted())
|
||||
{
|
||||
baseRequest.setServletPath(old_servlet_path);
|
||||
baseRequest.setPathInfo(old_path_info);
|
||||
|
||||
if (old_scope != null)
|
||||
baseRequest.setUserIdentityScope(old_scope);
|
||||
|
||||
if (!(DispatcherType.INCLUDE.equals(type)))
|
||||
{
|
||||
baseRequest.setServletPath(old_servlet_path);
|
||||
baseRequest.setPathInfo(old_path_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,253 @@
|
|||
package org.eclipse.jetty.servlet;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
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.Handler;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
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;
|
||||
|
||||
/**
|
||||
* This tests the correct functioning of the AsyncContext
|
||||
*
|
||||
* tests for #371649 and #371635
|
||||
*/
|
||||
public class AsyncContextTest
|
||||
{
|
||||
|
||||
private Server _server = new Server();
|
||||
private ServletContextHandler _contextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
|
||||
private LocalConnector _connector = new LocalConnector();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
_connector.setMaxIdleTime(30000);
|
||||
_server.setConnectors(new Connector[]
|
||||
{ _connector });
|
||||
|
||||
_contextHandler.setContextPath("/");
|
||||
_contextHandler.addServlet(new ServletHolder(new TestServlet()),"/servletPath");
|
||||
_contextHandler.addServlet(new ServletHolder(new TestServlet2()),"/servletPath2");
|
||||
|
||||
HandlerList handlers = new HandlerList();
|
||||
handlers.setHandlers(new Handler[]
|
||||
{ _contextHandler, new DefaultHandler() });
|
||||
|
||||
_server.setHandler(handlers);
|
||||
_server.start();
|
||||
}
|
||||
|
||||
@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"
|
||||
+ "Connection: close\r\n" + "\r\n";
|
||||
String responseString = _connector.getResponses(request);
|
||||
|
||||
BufferedReader br = new BufferedReader(new StringReader(responseString));
|
||||
|
||||
Assert.assertEquals("HTTP/1.1 200 OK",br.readLine());
|
||||
|
||||
br.readLine();// connection close
|
||||
br.readLine();// server
|
||||
br.readLine();// empty
|
||||
|
||||
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath", br.readLine());
|
||||
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath", br.readLine());
|
||||
Assert.assertEquals("async context gets right path in async","async:run:/servletPath", br.readLine());
|
||||
}
|
||||
|
||||
@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"
|
||||
+ "Connection: close\r\n" + "\r\n";
|
||||
String responseString = _connector.getResponses(request);
|
||||
|
||||
BufferedReader br = new BufferedReader(new StringReader(responseString));
|
||||
|
||||
Assert.assertEquals("HTTP/1.1 200 OK",br.readLine());
|
||||
|
||||
br.readLine();// connection close
|
||||
br.readLine();// server
|
||||
br.readLine();// empty
|
||||
|
||||
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath2", br.readLine());
|
||||
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath2", br.readLine());
|
||||
Assert.assertEquals("async context gets right path in async","async:run:/servletPath2", br.readLine());
|
||||
Assert.assertEquals("servlet path attr is original","async:run:attr:servletPath:/servletPath", br.readLine());
|
||||
Assert.assertEquals("path info attr is correct","async:run:attr:pathInfo:null", br.readLine());
|
||||
Assert.assertEquals("query string attr is correct","async:run:attr:queryString:dispatch=true", br.readLine());
|
||||
Assert.assertEquals("context path attr is correct","async:run:attr:contextPath:", br.readLine());
|
||||
Assert.assertEquals("request uri attr is correct","async:run:attr:requestURI:/servletPath", br.readLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
//Ignore ("test fails without a patch")
|
||||
public void testSimpleWithContextAsyncContext() throws Exception
|
||||
{
|
||||
_contextHandler.setContextPath("/foo");
|
||||
|
||||
String request = "GET /foo/servletPath 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));
|
||||
|
||||
Assert.assertEquals("HTTP/1.1 200 OK",br.readLine());
|
||||
|
||||
br.readLine();// connection close
|
||||
br.readLine();// server
|
||||
br.readLine();// empty
|
||||
|
||||
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath", br.readLine());
|
||||
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath", br.readLine());
|
||||
Assert.assertEquals("async context gets right path in async","async:run:/servletPath", br.readLine());
|
||||
}
|
||||
|
||||
@Test
|
||||
//Ignore ("test fails without a patch")
|
||||
public void testDispatchWithContextAsyncContext() throws Exception
|
||||
{
|
||||
_contextHandler.setContextPath("/foo");
|
||||
|
||||
String request = "GET /foo/servletPath?dispatch=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);
|
||||
|
||||
System.out.println(responseString);
|
||||
|
||||
BufferedReader br = new BufferedReader(new StringReader(responseString));
|
||||
|
||||
Assert.assertEquals("HTTP/1.1 200 OK",br.readLine());
|
||||
|
||||
br.readLine();// connection close
|
||||
br.readLine();// server
|
||||
br.readLine();// empty
|
||||
|
||||
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath2", br.readLine());
|
||||
Assert.assertEquals("async context gets right path in get","doGet:async:getServletPath:/servletPath2", br.readLine());
|
||||
Assert.assertEquals("async context gets right path in async","async:run:/servletPath2", br.readLine());
|
||||
Assert.assertEquals("servlet path attr is original","async:run:attr:servletPath:/servletPath", br.readLine());
|
||||
Assert.assertEquals("path info attr is correct","async:run:attr:pathInfo:null", br.readLine());
|
||||
Assert.assertEquals("query string attr is correct","async:run:attr:queryString:dispatch=true", br.readLine());
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception
|
||||
{
|
||||
_server.stop();
|
||||
_server.join();
|
||||
}
|
||||
|
||||
private class TestServlet extends HttpServlet
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
AsyncContinuation continuation = (AsyncContinuation) ContinuationSupport.getContinuation(request);
|
||||
|
||||
if (request.getParameter("dispatch") != null)
|
||||
{
|
||||
continuation.suspend();
|
||||
continuation.dispatch("/servletPath2");
|
||||
//AsyncContext asyncContext = request.startAsync(request,response);
|
||||
}
|
||||
else
|
||||
{
|
||||
response.getOutputStream().print("doGet:getServletPath:" + request.getServletPath() + "\n");
|
||||
|
||||
continuation.suspend();
|
||||
|
||||
//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));
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private class TestServlet2 extends HttpServlet
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
AsyncContinuation continuation = (AsyncContinuation) ContinuationSupport.getContinuation(request);
|
||||
|
||||
response.getOutputStream().print("doGet:getServletPath:" + request.getServletPath() + "\n");
|
||||
|
||||
continuation.suspend();
|
||||
//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));
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private class AsyncRunnable implements Runnable
|
||||
{
|
||||
private AsyncContinuation _continuation;
|
||||
|
||||
public AsyncRunnable(AsyncContinuation continuation)
|
||||
{
|
||||
_continuation = continuation;
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
HttpServletRequest req = (HttpServletRequest)_continuation.getRequest();
|
||||
|
||||
try
|
||||
{
|
||||
_continuation.getResponse().getOutputStream().print("async:run:" + req.getServletPath() + "\n");
|
||||
_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");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
_continuation.complete();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue