diff --git a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java index 114dd6aba07..0ec67228d95 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java +++ b/jetty-ee10/jetty-ee10-servlet/src/main/java/org/eclipse/jetty/ee10/servlet/DefaultServlet.java @@ -357,8 +357,13 @@ public class DefaultServlet extends HttpServlet @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String pathInContext = isPathInfoOnly() ? req.getPathInfo() : URIUtil.addPaths(req.getServletPath(), req.getPathInfo()); - boolean included = req.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; + String includedServletPath = (String)req.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); + boolean included = includedServletPath != null; + String pathInContext; + if (included) + pathInContext = getIncludedPathInContext(req, includedServletPath, isPathInfoOnly()); + else + pathInContext = URIUtil.addPaths(isPathInfoOnly() ? "/" : req.getServletPath(), req.getPathInfo()); if (LOG.isDebugEnabled()) LOG.debug("doGet(req={}, resp={}) pathInContext={}, included={}", req, resp, pathInContext, included); @@ -469,10 +474,16 @@ public class DefaultServlet extends HttpServlet fields.add(new HttpField(headerName, headerValue)); } } + _httpFields = fields.asImmutable(); - _uri = (request.getDispatcherType() == DispatcherType.REQUEST) - ? getWrapped().getHttpURI() - : Request.newHttpURIFrom(getWrapped(), URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo())); + String includedServletPath = (String)request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); + boolean included = includedServletPath != null; + if (request.getDispatcherType() == DispatcherType.REQUEST) + _uri = getWrapped().getHttpURI(); + else if (included) + _uri = Request.newHttpURIFrom(getWrapped(), getIncludedPathInContext(request, includedServletPath, false)); + else + _uri = Request.newHttpURIFrom(getWrapped(), URIUtil.addPaths(_servletRequest.getServletPath(), _servletRequest.getPathInfo())); } @Override @@ -904,22 +915,18 @@ public class DefaultServlet extends HttpServlet public String getWelcomeTarget(Request coreRequest) throws IOException { String[] welcomes = _servletContextHandler.getWelcomeFiles(); - if (welcomes == null) return null; HttpServletRequest request = getServletRequest(coreRequest); - - boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; - - if (included) - { - // Servlet 9.3 - don't process welcome target from INCLUDE dispatch - return null; - } - String pathInContext = Request.getPathInContext(coreRequest); - String requestTarget = isPathInfoOnly() ? request.getPathInfo() : pathInContext; + String requestTarget; + String includedServletPath = (String)request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); + boolean included = includedServletPath != null; + if (included) + requestTarget = getIncludedPathInContext(request, includedServletPath, isPathInfoOnly()); + else + requestTarget = isPathInfoOnly() ? request.getPathInfo() : pathInContext; String welcomeServlet = null; Resource base = _baseResource.resolve(requestTarget); @@ -951,7 +958,7 @@ public class DefaultServlet extends HttpServlet HttpServletRequest request = getServletRequest(coreRequest); HttpServletResponse response = getServletResponse(coreResponse); ServletContext context = request.getServletContext(); - boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; + boolean included = isIncluded(request); String welcome = welcomeAction.target(); if (LOG.isDebugEnabled()) @@ -1056,9 +1063,9 @@ public class DefaultServlet extends HttpServlet @Override protected boolean passConditionalHeaders(Request request, Response response, HttpContent content, Callback callback) throws IOException { - boolean included = getServletRequest(request).getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; + boolean included = isIncluded(getServletRequest(request)); if (included) - return true; + return false; return super.passConditionalHeaders(request, response, content, callback); } @@ -1075,6 +1082,18 @@ public class DefaultServlet extends HttpServlet } } + private static String getIncludedPathInContext(HttpServletRequest request, String includedServletPath, boolean isPathInfoOnly) + { + String servletPath = isPathInfoOnly ? "/" : includedServletPath; + String pathInfo = (String)request.getAttribute(RequestDispatcher.INCLUDE_PATH_INFO); + return URIUtil.addPaths(servletPath, pathInfo); + } + + private static boolean isIncluded(HttpServletRequest request) + { + return request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null; + } + /** * Wrap an existing HttpContent with one that takes has an unknown/unspecified length. */ diff --git a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java index a1ddc7b3adc..e4568d33e62 100644 --- a/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java +++ b/jetty-ee10/jetty-ee10-servlet/src/test/java/org/eclipse/jetty/ee10/servlet/DefaultServletTest.java @@ -113,7 +113,6 @@ public class DefaultServletTest connector = new LocalConnector(server); connector.getConnectionFactory(HttpConfiguration.ConnectionFactory.class).getHttpConfiguration().setSendServerVersion(false); - Path extraJarResources = MavenPaths.findTestResourceFile(ODD_JAR); URL[] urls = new URL[]{extraJarResources.toUri().toURL()}; @@ -1132,12 +1131,10 @@ public class DefaultServletTest } @Test - @Disabled("Not working as RequestDispatcher.include() isn't behaving as expected") public void testIncludedWelcomeDifferentBase() throws Exception { Path altRoot = workDir.getPath().resolve("altroot"); FS.ensureDirExists(altRoot); - Path altIndex = altRoot.resolve("index.html"); ServletHolder defholder = context.addServlet(DefaultServlet.class, "/alt/*"); defholder.setInitParameter("resourceBase", altRoot.toUri().toASCIIString()); @@ -1149,10 +1146,10 @@ public class DefaultServletTest ServletHolder gwholder = new ServletHolder("gateway", new HttpServlet() { @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - req.getRequestDispatcher("/alt/").include(req, resp); + String includeTarget = req.getParameter("includeTarget"); + req.getRequestDispatcher(includeTarget).include(req, resp); } }); context.addServlet(gwholder, "/gateway"); @@ -1160,9 +1157,9 @@ public class DefaultServletTest String rawResponse; HttpTester.Response response; - // Test included alt default + // Test an included a resource which does not exist. rawResponse = connector.getResponse(""" - GET /context/gateway HTTP/1.1\r + GET /context/gateway?includeTarget=/alt/thisResourceDoesNotExist HTTP/1.1\r Host: local\r Connection: close\r \r @@ -1177,9 +1174,20 @@ public class DefaultServletTest */ assertThat(response.toString(), response.getStatus(), is(HttpStatus.INTERNAL_SERVER_ERROR_500)); - Files.writeString(altIndex, "

Alt Index

", UTF_8); + // This resource does exist but directory listings are not allowed and there are no welcome files. rawResponse = connector.getResponse(""" - GET /context/gateway HTTP/1.1\r + GET /context/gateway?includeTarget=/alt/ HTTP/1.1\r + Host: local\r + Connection: close\r + \r + """); + response = HttpTester.parseResponse(rawResponse); + assertThat(response.toString(), response.getStatus(), is(HttpStatus.FORBIDDEN_403)); + + // Once index.html has been created we can include this same target and see it as a welcome file. + Files.writeString(altRoot.resolve("index.html"), "

Alt Index

", UTF_8); + rawResponse = connector.getResponse(""" + GET /context/gateway?includeTarget=/alt/ HTTP/1.1\r Host: local\r Connection: close\r \r