reopen HttpOutput in same places as Jetty 11

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2022-07-25 16:56:39 +10:00
parent 1ea6ec603a
commit 9efce15804
5 changed files with 60 additions and 23 deletions

View File

@ -125,8 +125,16 @@ public class Dispatcher implements RequestDispatcher
{
HttpServletRequest httpRequest = (request instanceof HttpServletRequest) ? (HttpServletRequest)request : new ServletRequestHttpWrapper(request);
HttpServletResponse httpResponse = (response instanceof HttpServletResponse) ? (HttpServletResponse)response : new ServletResponseHttpWrapper(response);
ServletContextResponse baseResponse = ServletContextResponse.getBaseResponse(response);
_mappedServlet.handle(_servletHandler, _pathInContext, new IncludeRequest(httpRequest), new IncludeResponse(httpResponse));
try
{
_mappedServlet.handle(_servletHandler, _pathInContext, new IncludeRequest(httpRequest), new IncludeResponse(httpResponse));
}
finally
{
baseResponse.included();
}
}
public void async(ServletRequest request, ServletResponse response) throws ServletException, IOException
@ -501,6 +509,7 @@ public class Dispatcher implements RequestDispatcher
{
super(httpRequest);
_httpServletRequest = httpRequest;
Objects.requireNonNull(_servletPathMapping);
}
@Override
@ -512,13 +521,22 @@ public class Dispatcher implements RequestDispatcher
@Override
public String getPathInfo()
{
return _mappedServlet.getServletPathMapping(_pathInContext).getPathInfo();
// TODO what about a 404 dispatch?
return Objects.requireNonNull(_servletPathMapping).getPathInfo();
}
@Override
public String getServletPath()
{
return _mappedServlet.getServletPathMapping(_pathInContext).getServletPath();
// TODO what about a 404 dispatch?
return Objects.requireNonNull(_servletPathMapping).getServletPath();
}
@Override
public HttpServletMapping getHttpServletMapping()
{
// TODO what about a 404 dispatch?
return Objects.requireNonNull(_servletPathMapping);
}
@Override

View File

@ -607,6 +607,7 @@ public class ServletChannel implements Runnable
{
try
{
_request.getResponse().getHttpOutput().reopen();
_servletContextApi.getContext().getServletContextHandler().requestInitialized(_request, _request.getHttpServletRequest());
_combinedListener.onBeforeDispatch(_request);
dispatchable.dispatch();

View File

@ -183,8 +183,7 @@ public class ServletContextRequest extends ContextRequest implements Runnable
public void errorClose()
{
// TODO Actually make the response status and headers immutable temporarily
// TODO: This soft close breaks ErrorPageTest, AsyncContextTest
// _response.getHttpOutput().softClose();
_response.getHttpOutput().softClose();
}
public boolean isHead()

View File

@ -134,11 +134,17 @@ public class ServletContextResponse extends ContextResponse
public void resetForForward()
{
_httpOutput.resetBuffer();
_httpOutput.reopen();
_httpServletResponse.resetBuffer();
_outputType = OutputType.NONE;
}
public void included()
{
if (_outputType == OutputType.WRITER)
_writer.reopen();
_httpOutput.reopen();
}
public void completeOutput(Callback callback)
{
if (_outputType == OutputType.WRITER)
@ -218,7 +224,7 @@ public class ServletContextResponse extends ContextResponse
{
super.reset();
_httpOutput.resetBuffer();
_httpServletResponse.resetBuffer();
_outputType = OutputType.NONE;
_contentLength = -1;
_contentType = null;
@ -695,6 +701,7 @@ public class ServletContextResponse extends ContextResponse
*/
public void sendRedirect(int code, String location) throws IOException
{
resetBuffer();
FutureCallback callback = new FutureCallback();
Response.sendRedirect(_request, ServletContextResponse.this, callback, code, location, false);
callback.block();

View File

@ -330,7 +330,6 @@ public class DispatcherTest
}
@Test
@Disabled("See ServletContextRequest.errorClose and softClose hack")
public void testForwardSendError() throws Exception
{
_contextHandler.addServlet(ForwardServlet.class, "/forward/*");
@ -549,7 +548,7 @@ public class DispatcherTest
}
@Test
@Disabled("References to ResourceHandler, a jetty-core ContextHandler cannot be referenced for a ServletContext")
@Disabled("Cross context dispatch not yet supported in jetty-12")
public void testIncludeToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
@ -568,7 +567,7 @@ public class DispatcherTest
}
@Test
@Disabled("References to ResourceHandler, a jetty-core ContextHandler cannot be referenced for a ServletContext")
@Disabled("Cross context dispatch not yet supported in jetty-12")
public void testForwardToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
@ -587,7 +586,7 @@ public class DispatcherTest
}
@Test
@Disabled("References to ResourceHandler, a jetty-core ContextHandler cannot be referenced for a ServletContext")
@Disabled("Cross context dispatch not yet supported in jetty-12")
public void testWrappedIncludeToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
@ -606,7 +605,7 @@ public class DispatcherTest
}
@Test
@Disabled("References to ResourceHandler, a jetty-core ContextHandler cannot be referenced for a ServletContext")
@Disabled("Cross context dispatch not yet supported in jetty-12")
public void testWrappedForwardToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
@ -675,17 +674,14 @@ public class DispatcherTest
}
@Test
@Disabled // TODO
public void testDispatchMapping() throws Exception
{
_contextHandler.addServlet(new ServletHolder("TestServlet", MappingServlet.class), "/TestServlet");
_contextHandler.addServlet(new ServletHolder("DispatchServlet", AsyncDispatch2TestServlet.class), "/DispatchServlet");
_contextHandler.addServlet(new ServletHolder("DispatchServlet2", AsyncDispatch2TestServlet.class), "/DispatchServlet2");
_contextHandler.addServlet(new ServletHolder("DispatchServlet", AsyncDispatchTestServlet.class), "/DispatchServlet");
HttpTester.Response response;
String rawResponse;
// TODO Test TCK hack for https://github.com/eclipse-ee4j/jakartaee-tck/issues/585
rawResponse = _connector.getResponse("""
GET /context/DispatchServlet HTTP/1.1\r
Host: local\r
@ -693,17 +689,31 @@ public class DispatcherTest
\r
""");
response = HttpTester.parseResponse(rawResponse);
assertThat(response.getContent(), containsString("matchValue=DispatchServlet, pattern=/DispatchServlet, servletName=DispatchServlet, mappingMatch=EXACT"));
assertThat(response.getContent(), containsString("matchValue=TestServlet, pattern=/TestServlet, servletName=TestServlet, mappingMatch=EXACT"));
}
// TODO Test how it should work after fix for https://github.com/eclipse-ee4j/jakartaee-tck/issues/585
@Test
public void testDispatchMapping404() throws Exception
{
_contextHandler.addServlet(new ServletHolder("TestServlet", MappingServlet.class), "/TestServlet");
_contextHandler.addServlet(new ServletHolder("DispatchServlet", AsyncDispatchTestServlet.class), "/DispatchServlet");
ErrorPageErrorHandler errorPageErrorHandler = new ErrorPageErrorHandler();
_contextHandler.setErrorProcessor(errorPageErrorHandler);
errorPageErrorHandler.addErrorPage(404, "/TestServlet");
HttpTester.Response response;
String rawResponse;
// Test not found
rawResponse = _connector.getResponse("""
GET /context/DispatchServlet2 HTTP/1.1\r
GET /context/DispatchServlet?target=/DoesNotExist HTTP/1.1\r
Host: local\r
Connection: close\r
\r
""");
response = HttpTester.parseResponse(rawResponse);
assertThat(response.getContent(), containsString("matchValue=TestServlet, pattern=/TestServlet, servletName=TestServlet, mappingMatch=EXACT"));
assertThat(response.getContent(), containsString("matchValue=DispatchServlet, pattern=/DispatchServlet, servletName=DispatchServlet, mappingMatch=EXACT"));
}
public static class WrappingFilter implements Filter
@ -1335,14 +1345,16 @@ public class DispatcherTest
}
}
public static class AsyncDispatch2TestServlet extends HttpServlet
public static class AsyncDispatchTestServlet extends HttpServlet
{
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException
{
AsyncContext asyncContext = req.startAsync();
asyncContext.setTimeout(0);
asyncContext.dispatch("/TestServlet");
String target = req.getParameter("target");
target = StringUtil.isBlank(target) ? "/TestServlet" : target;
asyncContext.dispatch(target);
}
}
}