DefaultServlet include effort (incomplete)

This commit is contained in:
Joakim Erdfelt 2022-07-14 15:56:49 -05:00
parent e1ee2e3fa2
commit da2af1141a
No known key found for this signature in database
GPG Key ID: 2D0E1FB8FE4B68B4
3 changed files with 58 additions and 25 deletions

View File

@ -170,7 +170,7 @@ public class ResourceService
sendData(request, response, callback, content, reqRanges);
}
// Can be thrown from contentFactory.getContent() call when using invalid characters
catch (InvalidPathException e)
catch (InvalidPathException e) // TODO: this cannot trigger here, as contentFactory.getContent() isn't called in this try block
{
if (LOG.isDebugEnabled())
LOG.debug("InvalidPathException for pathInContext: {}", pathInContext, e);

View File

@ -13,9 +13,11 @@
package org.eclipse.jetty.ee10.servlet;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.file.InvalidPathException;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Enumeration;
@ -30,6 +32,7 @@ import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import jakarta.servlet.DispatcherType;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
@ -314,31 +317,50 @@ public class DefaultServlet extends HttpServlet
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
// TODO: need special handling here for included if request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) is not null?
// Handling things like RequestDispatcher.INCLUDE_PATH_INFO?
// or is this handled elsewhere now?
String pathInContext = isPathInfoOnly() ? req.getPathInfo() : URIUtil.addPaths(req.getServletPath(), req.getPathInfo());
HttpContent content = _resourceService.getContent(pathInContext, resp.getBufferSize());
if (content == null)
boolean included = req.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null;
try
{
// no content
resp.setStatus(404);
HttpContent content = _resourceService.getContent(pathInContext, resp.getBufferSize());
if (content == null || !content.getResource().exists())
{
if (included)
{
/* https://github.com/jakartaee/servlet/blob/6.0.0-RELEASE/spec/src/main/asciidoc/servlet-spec-body.adoc#93-the-include-method
* 9.3 - If the default servlet is the target of a RequestDispatch.include() and the requested
* resource does not exist, then the default servlet MUST throw FileNotFoundException.
* If the exception isnt caught and handled, and the response
* hasnt been committed, the status code MUST be set to 500.
*/
throw new FileNotFoundException(pathInContext);
}
// no content
resp.setStatus(404);
}
else
{
// serve content
try (Blocker.Callback callback = Blocker.callback())
{
ServletCoreRequest coreRequest = new ServletCoreRequest(req);
ServletCoreResponse coreResponse = new ServletCoreResponse(coreRequest, resp);
_resourceService.doGet(coreRequest, coreResponse, callback, content);
callback.block();
}
catch (Exception e)
{
throw new ServletException(e);
}
}
}
else
catch (InvalidPathException e)
{
// serve content
try (Blocker.Callback callback = Blocker.callback())
{
ServletCoreRequest coreRequest = new ServletCoreRequest(req);
ServletCoreResponse coreResponse = new ServletCoreResponse(coreRequest, resp);
_resourceService.doGet(coreRequest, coreResponse, callback, content);
callback.block();
}
catch (Exception e)
{
throw new ServletException(e);
}
if (LOG.isDebugEnabled())
LOG.debug("InvalidPathException for pathInContext: {}", pathInContext, e);
if (included)
throw new FileNotFoundException(pathInContext);
resp.setStatus(404);
}
}
@ -798,6 +820,12 @@ public class DefaultServlet extends HttpServlet
HttpServletRequest request = getServletRequest(coreRequest);
if (request.getDispatcherType() == DispatcherType.INCLUDE)
{
// Servlet 9.3 - don't process welcome target from INCLUDE dispatch
return null;
}
String requestTarget = isPathInfoOnly() ? request.getPathInfo() : coreRequest.getPathInContext();
Resource base = _baseResource.resolve(requestTarget);

View File

@ -1030,7 +1030,7 @@ public class DefaultServletTest
}
@Test
@Disabled
@Disabled("Not working as RequestDispatcher.include() isn't behaving as expected")
public void testIncludedWelcomeDifferentBase() throws Exception
{
Path altRoot = workDir.getPath().resolve("altroot");
@ -1066,8 +1066,13 @@ public class DefaultServletTest
\r
""");
response = HttpTester.parseResponse(rawResponse);
// 9.3 "The Include Method" - when include() is used, FileNotFoundException (and HTTP 500)
// should be used
/* https://github.com/jakartaee/servlet/blob/6.0.0-RELEASE/spec/src/main/asciidoc/servlet-spec-body.adoc#93-the-include-method
* 9.3 - If the default servlet is the target of a RequestDispatch.include() and the requested
* resource does not exist, then the default servlet MUST throw FileNotFoundException.
* If the exception isnt caught and handled, and the response
* hasnt been committed, the status code MUST be set to 500.
*/
assertThat(response.toString(), response.getStatus(), is(HttpStatus.INTERNAL_SERVER_ERROR_500));
Files.writeString(altIndex, "<h1>Alt Index</h1>", UTF_8);