From f17a5fb3fe38408b8d3a74d9e995cdfe739623e2 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Fri, 11 Dec 2020 10:04:31 +0100 Subject: [PATCH] Fixes #5779 Include should not set pathInContext (#5780) Fixes #5779 by ensuring that ContextHandler does not set pathInContext for include. --- .../jetty/server/handler/ContextHandler.java | 17 ++-- .../eclipse/jetty/servlet/DispatcherTest.java | 88 +++++++++++++++++++ 2 files changed, 98 insertions(+), 7 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index f99bba013b26..ebddd43a4620 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -1225,7 +1225,7 @@ public void doScope(String target, Request baseRequest, HttpServletRequest reque final Thread currentThread = Thread.currentThread(); final ClassLoader oldClassloader = currentThread.getContextClassLoader(); Context oldContext; - String oldPathInContext = null; + String oldPathInContext = baseRequest.getPathInContext();; String pathInContext = target; DispatcherType dispatch = baseRequest.getDispatcherType(); @@ -1267,14 +1267,15 @@ else if (_contextPath.length() == 1) try { - oldPathInContext = baseRequest.getPathInContext(); - // Update the paths - baseRequest.setContext(_scontext, pathInContext); - __context.set(_scontext); + baseRequest.setContext(_scontext, + (DispatcherType.INCLUDE.equals(dispatch) || !target.startsWith("/")) ? oldPathInContext : pathInContext); if (oldContext != _scontext) + { + __context.set(_scontext); enterScope(baseRequest, dispatch); + } if (LOG.isDebugEnabled()) LOG.debug("context={}|{}|{} @ {}", baseRequest.getContextPath(), baseRequest.getServletPath(), baseRequest.getPathInfo(), this); @@ -1291,10 +1292,12 @@ else if (_contextPath.length() == 1) if (_classLoader != null) currentThread.setContextClassLoader(oldClassloader); - // reset the context and servlet path. - baseRequest.setContext(oldContext, oldPathInContext); + // reset the context __context.set(oldContext); } + + // reset pathInContext + baseRequest.setContext(oldContext, oldPathInContext); } } diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java index 816cde4232fc..5df46e8893dc 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java @@ -259,6 +259,44 @@ public void testInclude() throws Exception assertEquals(expected, responses); } + @Test + public void testForwardExForwardEx() throws Exception + { + _contextHandler.addServlet(RelativeDispatch2Servlet.class, "/RelDispatchServlet/*"); + _contextHandler.addServlet(ThrowServlet.class, "/include/throw/*"); + String expected = + "HTTP/1.1 200 OK\r\n" + + "Content-Length: 56\r\n" + + "\r\n" + + "THROWING\r\n" + + "CAUGHT2 java.io.IOException: Expected\r\n" + + "AFTER\r\n"; + + String responses = _connector.getResponse("GET /context/RelDispatchServlet?path=include/throw HTTP/1.0\n\n"); + assertEquals(expected, responses); + } + + @Test + public void testIncludeExIncludeEx() throws Exception + { + _contextHandler.addServlet(RelativeDispatch2Servlet.class, "/RelDispatchServlet/*"); + _contextHandler.addServlet(ThrowServlet.class, "/include/throw/*"); + String expected = + "HTTP/1.1 200 OK\r\n" + + "Content-Length: 122\r\n" + + "\r\n" + + "BEFORE\r\n" + + "THROWING\r\n" + + "CAUGHT1 java.io.IOException: Expected\r\n" + + "BETWEEN\r\n" + + "THROWING\r\n" + + "CAUGHT2 java.io.IOException: Expected\r\n" + + "AFTER\r\n"; + + String responses = _connector.getResponse("GET /context/RelDispatchServlet?include=true&path=include/throw HTTP/1.0\n\n"); + assertEquals(expected, responses); + } + @Test public void testForwardThenInclude() throws Exception { @@ -670,6 +708,46 @@ else if (request.getParameter("do").equals("assertinclude")) } } + public static class RelativeDispatch2Servlet extends HttpServlet implements Servlet + { + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException + { + RequestDispatcher dispatcher = null; + String path = request.getParameter("path"); + String include = request.getParameter("include"); + ServletOutputStream out = response.getOutputStream(); + try + { + out.println("BEFORE"); + if (Boolean.parseBoolean(include)) + request.getRequestDispatcher(path).include(request, response); + else + request.getRequestDispatcher(path).forward(request, response); + out.println("AFTER1"); + } + catch (Throwable t) + { + out.println("CAUGHT1 " + t); + } + + try + { + out.println("BETWEEN"); + if (Boolean.parseBoolean(include)) + request.getRequestDispatcher(path).include(request, response); + else + request.getRequestDispatcher(path).forward(request, response); + out.println("AFTER2"); + } + catch (Throwable t) + { + out.println("CAUGHT2 " + t); + } + out.println("AFTER"); + } + } + public static class RogerThatServlet extends GenericServlet { @Override @@ -679,6 +757,16 @@ public void service(ServletRequest req, ServletResponse res) throws ServletExcep } } + public static class ThrowServlet extends GenericServlet + { + @Override + public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException + { + res.getOutputStream().println("THROWING"); + throw new IOException("Expected"); + } + } + public static class EchoServlet extends GenericServlet { @Override