Merge pull request #9193 from eclipse/jetty-12.0.x-9067-DefaultServletInclude

Issue #9067 - Fixes to include dispatch for pathInContext and welcome files.
This commit is contained in:
Lachlan 2023-02-06 12:23:07 +11:00 committed by GitHub
commit 39c0c09fec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 56 additions and 29 deletions

View File

@ -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.
*/

View File

@ -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, "<h1>Alt Index</h1>", 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"), "<h1>Alt Index</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/gateway?includeTarget=/alt/ HTTP/1.1\r
Host: local\r
Connection: close\r
\r