Fixing DefaultServletTest.testWelcomeMultipleDefaultServletsDifferentBases

This commit is contained in:
Joakim Erdfelt 2022-07-14 15:33:02 -05:00
parent 7133c0827e
commit e1ee2e3fa2
No known key found for this signature in database
GPG Key ID: 2D0E1FB8FE4B68B4
6 changed files with 228 additions and 195 deletions

View File

@ -177,6 +177,7 @@ public class CachingContentFactory implements HttpContent.ContentFactory
else
removeFromCache(cachingHttpContent);
}
HttpContent httpContent = _authority.getContent(path, maxBuffer);
// Do not cache directories or files that are too big
if (httpContent != null && !httpContent.getResource().isDirectory() && httpContent.getContentLengthValue() <= _maxCachedFileSize)

View File

@ -19,7 +19,6 @@ import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
@ -43,7 +42,6 @@ import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.IteratingCallback;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -59,7 +57,6 @@ public class ResourceService
private static final int NO_CONTENT_LENGTH = -1;
private static final int USE_KNOWN_CONTENT_LENGTH = -2;
private boolean _pathInfoOnly = false;
private CompressedContentFormat[] _precompressedFormats = new CompressedContentFormat[0];
private WelcomeFactory _welcomeFactory;
private boolean _redirectWelcome = false;
@ -392,7 +389,7 @@ public class ResourceService
}
}
// look for a welcome file
// process optional Welcome behaviors
if (welcome(request, response, callback))
return;
@ -400,41 +397,81 @@ public class ResourceService
sendDirectory(request, response, content, callback, pathInContext);
}
public enum WelcomeActionType
{
REDIRECT,
SERVE
}
/**
* Behavior for a potential welcome action
* as determined by {@link ResourceService#processWelcome(Request, Response)}
*
* <p>
* For {@link WelcomeActionType#REDIRECT} this is the resulting `Location` response header.
* For {@link WelcomeActionType#SERVE} this is the resulting path to for welcome serve, note that
* this is just a path, and can point to a real file, or a dynamic handler for
* welcome processing (such as Jetty core Handler, or EE Servlet), it's up
* to the implementation of {@link ResourceService#welcome(Request, Response, Callback)}
* to handle the various action types.
* </p>
* @param type the type of action
* @param target The target URI path of the action.
*/
public record WelcomeAction(WelcomeActionType type, String target) {}
protected boolean welcome(Request request, Response response, Callback callback) throws IOException
{
String pathInContext = request.getPathInContext();
String welcome = _welcomeFactory == null ? null : _welcomeFactory.getWelcomeFile(pathInContext);
if (welcome != null)
WelcomeAction welcomeAction = processWelcome(request, response);
if (welcomeAction == null)
return false;
switch (welcomeAction.type)
{
String contextPath = request.getContext().getContextPath();
if (_pathInfoOnly)
welcome = URIUtil.addPaths(contextPath, welcome);
if (LOG.isDebugEnabled())
LOG.debug("welcome={}", welcome);
if (_redirectWelcome)
case REDIRECT ->
{
// Redirect to the index
response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, 0);
// TODO need URI util that handles param and query without reconstructing entire URI with scheme and authority
HttpURI.Mutable uri = HttpURI.build(request.getHttpURI());
String parameter = uri.getParam();
uri.path(URIUtil.addPaths(request.getContext().getContextPath(), welcome));
uri.param(parameter);
Response.sendRedirect(request, response, callback, uri.getPathQuery());
Response.sendRedirect(request, response, callback, welcomeAction.target);
return true;
}
case SERVE ->
{
// TODO output buffer size????
HttpContent c = _contentFactory.getContent(welcomeAction.target, 16 * 1024);
sendData(request, response, callback, c, null);
return true;
}
// Serve welcome file
HttpContent c = _contentFactory.getContent(welcome, 16 * 1024); // TODO output buffer size????
sendData(request, response, callback, c, null);
return true;
}
return false;
}
protected WelcomeAction processWelcome(Request request, Response response) throws IOException
{
String welcomeTarget = _welcomeFactory.getWelcomeTarget(request);
if (welcomeTarget == null)
return null;
String contextPath = request.getContext().getContextPath();
if (LOG.isDebugEnabled())
LOG.debug("welcome={}", welcomeTarget);
if (_redirectWelcome)
{
// Redirect to the index
response.getHeaders().putLongField(HttpHeader.CONTENT_LENGTH, 0);
// TODO need URI util that handles param and query without reconstructing entire URI with scheme and authority
HttpURI.Mutable uri = HttpURI.build(request.getHttpURI());
String parameter = uri.getParam();
uri.path(URIUtil.addPaths(request.getContext().getContextPath(), welcomeTarget));
uri.param(parameter);
return new WelcomeAction(WelcomeActionType.REDIRECT, uri.getPathQuery());
}
// Serve welcome file
return new WelcomeAction(WelcomeActionType.SERVE, welcomeTarget);
}
private void sendDirectory(Request request, Response response, HttpContent httpContent, Callback callback, String pathInContext) throws IOException
{
if (!_dirAllowed)
@ -678,14 +715,6 @@ public class ResourceService
return _precompressedFormats;
}
/**
* @return true, only the path info will be applied to the resourceBase
*/
public boolean isPathInfoOnly()
{
return _pathInfoOnly;
}
/**
* @return If true, welcome files are redirected rather than forwarded to.
*/
@ -761,14 +790,6 @@ public class ResourceService
return _encodingCacheSize;
}
/**
* @param pathInfoOnly true, only the path info will be applied to the resourceBase
*/
public void setPathInfoOnly(boolean pathInfoOnly)
{
_pathInfoOnly = pathInfoOnly;
}
/**
* @param redirectWelcome If true, welcome files are redirected rather than forwarded to.
* redirection is always used if the ResourceHandler is not scoped by
@ -786,14 +807,14 @@ public class ResourceService
public interface WelcomeFactory
{
/**
* Finds a matching welcome file for the supplied {@link Resource}.
* TODO would be better to pass back a URI or a Resource
* @param pathInContext the path of the request
* @return The path of the matching welcome file in context or null.
* Finds a matching welcome target URI path for the request.
*
* @param request the request to use to determine the matching welcome target from.
* @return The URI path of the matching welcome target in context or null
* (null means no welcome target was found)
*/
String getWelcomeFile(String pathInContext) throws IOException;
String getWelcomeTarget(Request request) throws IOException;
}
private static class ContentWriterIteratingCallback extends IteratingCallback

View File

@ -81,15 +81,15 @@ public class ResourceHandler extends Handler.Wrapper
{
HttpContent.ContentFactory contentFactory = new CachingContentFactory(new ResourceContentFactory(_resourceBase, _mimeTypes, _resourceService.getPrecompressedFormats()));
_resourceService.setContentFactory(contentFactory);
_resourceService.setWelcomeFactory(pathInContext ->
_resourceService.setWelcomeFactory(request ->
{
if (_welcomes == null)
return null;
for (String welcome : _welcomes)
{
String welcomeInContext = URIUtil.addPaths(pathInContext, welcome);
Resource welcomePath = _resourceBase.resolve(pathInContext).resolve(welcome);
String welcomeInContext = URIUtil.addPaths(request.getPathInContext(), welcome);
Resource welcomePath = _resourceBase.resolve(request.getPathInContext()).resolve(welcome);
if (welcomePath != null && welcomePath.exists())
return welcomeInContext;
}
@ -204,14 +204,6 @@ public class ResourceHandler extends Handler.Wrapper
return _resourceService.getPrecompressedFormats();
}
/**
* @return true, only the path info will be applied to the resourceBase
*/
public boolean isPathInfoOnly()
{
return _resourceService.isPathInfoOnly();
}
/**
* @return If true, welcome files are redirected rather than forwarded to.
*/
@ -296,14 +288,6 @@ public class ResourceHandler extends Handler.Wrapper
setupContentFactory();
}
/**
* @param pathInfoOnly true, only the path info will be applied to the resourceBase
*/
public void setPathInfoOnly(boolean pathInfoOnly)
{
_resourceService.setPathInfoOnly(pathInfoOnly);
}
/**
* @param redirectWelcome If true, welcome files are redirected rather than forwarded to.
* redirection is always used if the ResourceHandler is not scoped by

View File

@ -75,10 +75,13 @@ public class DefaultServlet extends HttpServlet
private boolean _welcomeExactServlets = false;
private Resource.Mount _resourceBaseMount;
private Resource _baseResource;
private Resource.Mount _stylesheetMount;
private Resource _stylesheet;
private boolean _useFileMappedBuffer = false;
private boolean _isPathInfoOnly = false;
@Override
public void init() throws ServletException
{
@ -86,7 +89,7 @@ public class DefaultServlet extends HttpServlet
_resourceService = new ServletResourceService(servletContextHandler);
_resourceService.setWelcomeFactory(_resourceService);
Resource baseResource = servletContextHandler.getResourceBase();
_baseResource = servletContextHandler.getResourceBase();
String rb = getInitParameter("resourceBase");
if (rb != null)
{
@ -94,7 +97,7 @@ public class DefaultServlet extends HttpServlet
{
URI resourceUri = Resource.toURI(rb);
_resourceBaseMount = Resource.mountIfNeeded(resourceUri);
baseResource = Resource.newResource(resourceUri);
_baseResource = Resource.newResource(resourceUri);
}
catch (Exception e)
{
@ -109,7 +112,7 @@ public class DefaultServlet extends HttpServlet
CompressedContentFormat[] precompressedFormats = new CompressedContentFormat[0];
_useFileMappedBuffer = getInitBoolean("useFileMappedBuffer", _useFileMappedBuffer);
ResourceContentFactory resourceContentFactory = new ResourceContentFactory(baseResource, mimeTypes, precompressedFormats);
ResourceContentFactory resourceContentFactory = new ResourceContentFactory(_baseResource, mimeTypes, precompressedFormats);
CachingContentFactory cached = new CachingContentFactory(resourceContentFactory, _useFileMappedBuffer);
int maxCacheSize = getInitInt("maxCacheSize", -2);
@ -145,9 +148,10 @@ public class DefaultServlet extends HttpServlet
_resourceService.setDirAllowed(getInitBoolean("dirAllowed", _resourceService.isDirAllowed()));
_resourceService.setRedirectWelcome(getInitBoolean("redirectWelcome", _resourceService.isRedirectWelcome()));
_resourceService.setPrecompressedFormats(parsePrecompressedFormats(getInitParameter("precompressed"), getInitBoolean("gzip"), _resourceService.getPrecompressedFormats()));
_resourceService.setPathInfoOnly(getInitBoolean("pathInfoOnly", _resourceService.isPathInfoOnly()));
_resourceService.setEtags(getInitBoolean("etags", _resourceService.isEtags()));
_isPathInfoOnly = getInitBoolean("pathInfoOnly", _isPathInfoOnly);
if ("exact".equals(getInitParameter("welcomeServlets")))
{
_welcomeExactServlets = true;
@ -216,7 +220,7 @@ public class DefaultServlet extends HttpServlet
// TODO: remove? _servletHandler = _contextHandler.getChildHandlerByClass(ServletHandler.class);
if (LOG.isDebugEnabled())
LOG.debug("base resource = {}", baseResource);
LOG.debug("base resource = {}", _baseResource);
}
@Override
@ -302,10 +306,19 @@ public class DefaultServlet extends HttpServlet
servletContext.getClass().getName() + " is not " + ContextHandler.Context.class.getName());
}
protected boolean isPathInfoOnly()
{
return _isPathInfoOnly;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
String pathInContext = _resourceService.isPathInfoOnly() ? req.getPathInfo() : URIUtil.addPaths(req.getServletPath(), req.getPathInfo());
// 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)
{
@ -776,20 +789,23 @@ public class DefaultServlet extends HttpServlet
}
@Override
public String getWelcomeFile(String pathInContext) throws IOException
public String getWelcomeTarget(Request coreRequest) throws IOException
{
String[] welcomes = _servletContextHandler.getWelcomeFiles();
if (welcomes == null)
return null;
// TODO this feels inefficient
Resource base = _servletContextHandler.getResourceBase().resolve(pathInContext);
HttpServletRequest request = getServletRequest(coreRequest);
String requestTarget = isPathInfoOnly() ? request.getPathInfo() : coreRequest.getPathInContext();
Resource base = _baseResource.resolve(requestTarget);
String welcomeServlet = null;
for (String welcome : welcomes)
{
Resource welcomePath = base.resolve(welcome);
String welcomeInContext = URIUtil.addPaths(pathInContext, welcome);
String welcomeInContext = URIUtil.addPaths(coreRequest.getPathInContext(), welcome);
if (welcomePath != null && welcomePath.exists())
return welcomeInContext;
@ -806,81 +822,92 @@ public class DefaultServlet extends HttpServlet
}
@Override
protected boolean welcome(Request rq, Response rs, Callback callback) throws IOException
protected boolean welcome(Request coreRequest, Response coreResponse, Callback callback) throws IOException
{
// TODO The contract of this method is very confused: it has a callback a return and throws?
// TODO, this unwrapping is fragile
HttpServletRequest request = ((ServletCoreRequest)rq)._request;
HttpServletResponse response = ((ServletCoreResponse)rs)._response;
String pathInContext = rq.getPathInContext();
WelcomeFactory welcomeFactory = getWelcomeFactory();
String welcome = welcomeFactory == null ? null : welcomeFactory.getWelcomeFile(pathInContext);
HttpServletRequest request = getServletRequest(coreRequest);
HttpServletResponse response = getServletResponse(coreResponse);
boolean included = request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null;
if (welcome == null)
WelcomeAction welcomeAction = super.processWelcome(coreRequest, coreResponse);
if (welcomeAction == null)
return false;
String servletPath = included ? (String)request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH)
: request.getServletPath();
if (isPathInfoOnly())
welcome = URIUtil.addPaths(servletPath, welcome);
String welcome = welcomeAction.target();
if (LOG.isDebugEnabled())
LOG.debug("welcome={}", welcome);
ServletContext context = request.getServletContext();
if (isRedirectWelcome() || context == null)
switch (welcomeAction.type())
{
// Redirect to the index
response.setContentLength(0);
// TODO need URI util that handles param and query without reconstructing entire URI with scheme and authority
HttpURI.Mutable uri = HttpURI.build(rq.getHttpURI());
String parameter = uri.getParam();
uri.path(URIUtil.addPaths(rq.getContext().getContextPath(), welcome));
uri.param(parameter);
response.sendRedirect(response.encodeRedirectURL(uri.getPathQuery()));
callback.succeeded();
return true;
}
RequestDispatcher dispatcher = context.getRequestDispatcher(URIUtil.encodePath(welcome));
if (dispatcher != null)
{
// Forward to the index
try
case REDIRECT ->
{
if (included)
if (isRedirectWelcome() || context == null)
{
dispatcher.include(request, response);
String servletPath = included ? (String)request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH)
: request.getServletPath();
if (isPathInfoOnly())
welcome = URIUtil.addPaths(servletPath, welcome);
response.setContentLength(0);
response.sendRedirect(welcome);
callback.succeeded();
return true;
}
else
{
request.setAttribute("org.eclipse.jetty.server.welcome", welcome);
dispatcher.forward(request, response);
}
callback.succeeded();
return true;
}
catch (ServletException e)
case SERVE ->
{
callback.failed(e);
RequestDispatcher dispatcher = context.getRequestDispatcher(welcome);
if (dispatcher != null)
{
// Forward to the index
try
{
if (included)
{
dispatcher.include(request, response);
}
else
{
request.setAttribute("org.eclipse.jetty.server.welcome", welcomeAction.target());
dispatcher.forward(request, response);
}
callback.succeeded();
return true;
}
catch (ServletException e)
{
callback.failed(e);
return true;
}
}
return true;
}
}
return false;
}
@Override
protected boolean passConditionalHeaders(Request request, Response response, HttpContent content, Callback callback) throws IOException
{
boolean included = ((ServletCoreRequest)request)._request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null;
boolean included = getServletRequest(request).getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null;
if (included)
return true;
return super.passConditionalHeaders(request, response, content, callback);
}
private HttpServletRequest getServletRequest(Request request)
{
// TODO, this unwrapping is fragile
return ((ServletCoreRequest)request)._request;
}
private HttpServletResponse getServletResponse(Response response)
{
// TODO, this unwrapping is fragile
return ((ServletCoreResponse)response)._response;
}
}
}

View File

@ -15,7 +15,6 @@ package org.eclipse.jetty.ee10.servlet;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
@ -153,7 +152,7 @@ public class DefaultServletTest
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.NOT_FOUND_404));
createFile(file, "How now brown cow");
Files.writeString(file, "How now brown cow", UTF_8);
rawResponse = connector.getResponse("""
GET /context/file.txt HTTP/1.1\r
@ -418,7 +417,6 @@ public class DefaultServletTest
}
@Test
@Disabled
public void testListingProperUrlEncoding() throws Exception
{
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/*");
@ -710,7 +708,7 @@ public class DefaultServletTest
/* create some content in the docroot */
Path index = docRoot.resolve("index.html");
createFile(index, "<h1>Hello Index</h1>");
Files.writeString(index, "<h1>Hello Index</h1>", UTF_8);
if (!OS.WINDOWS.isCurrentOs())
{
@ -725,7 +723,7 @@ public class DefaultServletTest
Path sekret = workDir.getPath().resolve("sekret");
FS.ensureDirExists(sekret);
Path pass = sekret.resolve("pass");
createFile(pass, "Sssh, you shouldn't be seeing this");
Files.writeString(pass, "Sssh, you shouldn't be seeing this", UTF_8);
/* At this point we have the following
* testListingContextBreakout/
@ -814,11 +812,11 @@ public class DefaultServletTest
FS.ensureDirExists(two);
FS.ensureDirExists(three);
createFile(one.resolve("index.htm"), "<h1>Hello Inde</h1>");
createFile(two.resolve("index.html"), "<h1>Hello Index</h1>");
Files.writeString(one.resolve("index.htm"), "<h1>Hello Inde</h1>", UTF_8);
Files.writeString(two.resolve("index.html"), "<h1>Hello Index</h1>", UTF_8);
createFile(three.resolve("index.html"), "<h1>Three Index</h1>");
createFile(three.resolve("index.htm"), "<h1>Three Inde</h1>");
Files.writeString(three.resolve("index.html"), "<h1>Three Index</h1>", UTF_8);
Files.writeString(three.resolve("index.htm"), "<h1>Three Inde</h1>", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "false");
@ -841,8 +839,7 @@ public class DefaultServletTest
}
@Test
@Disabled
public void testWelcomeMultipleBasesBase() throws Exception
public void testWelcomeMultipleDefaultServletsDifferentBases() throws Exception
{
Path dir = docRoot.resolve("dir");
FS.ensureDirExists(dir);
@ -892,9 +889,9 @@ public class DefaultServletTest
""");
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.MOVED_TEMPORARILY_302));
assertThat(response, containsHeaderValue("Location", "http://0.0.0.0/context/other/"));
assertThat(response, containsHeaderValue("Location", "http://local/context/other/"));
// Test alt default
// Test alt default, should see no directory listing output (dirAllowed == false per config)
rawResponse = connector.getResponse("""
GET /context/alt/dir/ HTTP/1.1\r
Host: local\r
@ -904,7 +901,9 @@ public class DefaultServletTest
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.FORBIDDEN_403));
createFile(altIndex, "<h1>Alt Index</h1>");
// Test alt welcome file, there's no index.html here yet, so let's create it and try
// accessing it directly
Files.writeString(altIndex, "<h1>Alt Index</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/alt/dir/index.html HTTP/1.1\r
Host: local\r
@ -915,6 +914,8 @@ public class DefaultServletTest
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertThat(response.getContent(), containsString("<h1>Alt Index</h1>"));
// Test alt welcome file, there now exists an index.html, lets try accessing
// it via the welcome file behaviors
rawResponse = connector.getResponse("""
GET /context/alt/dir/ HTTP/1.1\r
Host: local\r
@ -925,7 +926,10 @@ public class DefaultServletTest
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertThat(response.getContent(), containsString("<h1>Alt Index</h1>"));
createFile(altInde, "<h1>Alt Inde</h1>");
// Let's create an index.htm (no 'l') and see if the welcome file logic holds,
// we should still see the original `index.html` as that's the first welcome
// file listed
Files.writeString(altInde, "<h1>Alt Inde</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/alt/dir/ HTTP/1.1\r
Host: local\r
@ -936,8 +940,12 @@ public class DefaultServletTest
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertThat(response.getContent(), containsString("<h1>Alt Index</h1>"));
// Let's try deleting the `index.html` and accesing the welcome file at `index.htm`
// We skip this section of the test if the OS or filesystem doesn't support instantaneous delete
// such as what happens on Microsoft Windows.
if (deleteFile(altIndex))
{
// Access welcome file `index.htm` via the directory request.
rawResponse = connector.getResponse("""
GET /context/alt/dir/ HTTP/1.1\r
Host: local\r
@ -948,6 +956,8 @@ public class DefaultServletTest
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertThat(response.getContent(), containsString("<h1>Alt Inde</h1>"));
// Delete the welcome file `index.htm`, and access the directory.
// We should see no directory listing output (dirAllowed == false per config)
if (deleteFile(altInde))
{
rawResponse = connector.getResponse("""
@ -971,7 +981,7 @@ public class DefaultServletTest
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.FORBIDDEN_403));
createFile(index, "<h1>Hello Index</h1>");
Files.writeString(index, "<h1>Hello Index</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/dir/ HTTP/1.1\r
Host: local\r
@ -982,7 +992,7 @@ public class DefaultServletTest
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertThat(response.getContent(), containsString("<h1>Hello Index</h1>"));
createFile(inde, "<h1>Hello Inde</h1>");
Files.writeString(inde, "<h1>Hello Inde</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/dir/ HTTP/1.1\r
Host: local\r
@ -1060,7 +1070,7 @@ public class DefaultServletTest
// should be used
assertThat(response.toString(), response.getStatus(), is(HttpStatus.INTERNAL_SERVER_ERROR_500));
createFile(altIndex, "<h1>Alt Index</h1>");
Files.writeString(altIndex, "<h1>Alt Index</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/gateway HTTP/1.1\r
Host: local\r
@ -1105,7 +1115,7 @@ public class DefaultServletTest
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.FORBIDDEN_403));
createFile(index, "<h1>Hello Index</h1>");
Files.writeString(index, "<h1>Hello Index</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/dir/ HTTP/1.1\r
Host: local\r
@ -1116,7 +1126,7 @@ public class DefaultServletTest
assertThat(response.toString(), response.getStatus(), is(HttpStatus.MOVED_TEMPORARILY_302));
assertThat(response, headerValue("Location", "http://local/context/dir/index.html"));
createFile(inde, "<h1>Hello Inde</h1>");
Files.writeString(inde, "<h1>Hello Inde</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/dir HTTP/1.1\r
Host: local\r
@ -1169,7 +1179,7 @@ public class DefaultServletTest
Path dir = docRoot.resolve("dir");
FS.ensureDirExists(dir);
Path index = dir.resolve("index.html");
createFile(index, "<h1>Hello Index</h1>");
Files.writeString(index, "<h1>Hello Index</h1>", UTF_8);
context.addAliasCheck((p, r) -> true);
connector.getConnectionFactory(HttpConfiguration.ConnectionFactory.class).getHttpConfiguration().setRelativeRedirectAllowed(true);
@ -1228,7 +1238,7 @@ public class DefaultServletTest
Path dir = assumeMkDirSupported(docRoot, "dir?");
Path index = dir.resolve("index.html");
createFile(index, "<h1>Hello Index</h1>");
Files.writeString(index, "<h1>Hello Index</h1>", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "false");
@ -1280,7 +1290,7 @@ public class DefaultServletTest
Path dir = assumeMkDirSupported(docRoot, "dir;");
Path index = dir.resolve("index.html");
createFile(index, "<h1>Hello Index</h1>");
Files.writeString(index, "<h1>Hello Index</h1>", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "false");
@ -1299,7 +1309,7 @@ public class DefaultServletTest
""");
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.MOVED_TEMPORARILY_302));
assertThat(response, containsHeaderValue("Location", "http://0.0.0.0/context/dir%3B/"));
assertThat(response, containsHeaderValue("Location", "http://local/context/dir%3B/"));
rawResponse = connector.getResponse("""
GET /context/dir%3B/ HTTP/1.1\r
@ -1309,7 +1319,7 @@ public class DefaultServletTest
""");
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.MOVED_TEMPORARILY_302));
assertThat(response, containsHeaderValue("Location", "http://0.0.0.0/context/dir%3B/index.html"));
assertThat(response, containsHeaderValue("Location", "http://local/context/dir%3B/index.html"));
}
@Test
@ -1340,7 +1350,7 @@ public class DefaultServletTest
assertThat(response.toString(), response.getStatus(), is(HttpStatus.INTERNAL_SERVER_ERROR_500));
assertThat(response.getContent(), containsString("JSP support not configured"));
createFile(index, "<h1>Hello Index</h1>");
Files.writeString(index, "<h1>Hello Index</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/ HTTP/1.1\r
Host: local\r
@ -1351,7 +1361,7 @@ public class DefaultServletTest
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertThat(response.getContent(), containsString("<h1>Hello Index</h1>"));
createFile(inde, "<h1>Hello Inde</h1>");
Files.writeString(inde, "<h1>Hello Inde</h1>", UTF_8);
rawResponse = connector.getResponse("""
GET /context/ HTTP/1.1\r
Host: local\r
@ -1401,7 +1411,7 @@ public class DefaultServletTest
Path foobar = dir.resolve("foobar.txt");
Path link = dir.resolve("link.txt");
Path rLink = dir.resolve("rlink.txt");
createFile(foobar, "Foo Bar");
Files.writeString(foobar, "Foo Bar", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("gzip", "false");
@ -1579,11 +1589,11 @@ public class DefaultServletTest
FS.ensureDirExists(two);
FS.ensureDirExists(three);
createFile(one.resolve("index.htm"), "<h1>Hello Inde</h1>");
createFile(two.resolve("index.html"), "<h1>Hello Index</h1>");
Files.writeString(one.resolve("index.htm"), "<h1>Hello Inde</h1>", UTF_8);
Files.writeString(two.resolve("index.html"), "<h1>Hello Index</h1>", UTF_8);
createFile(three.resolve("index.html"), "<h1>Three Index</h1>");
createFile(three.resolve("index.htm"), "<h1>Three Inde</h1>");
Files.writeString(three.resolve("index.html"), "<h1>Three Index</h1>", UTF_8);
Files.writeString(three.resolve("index.htm"), "<h1>Three Inde</h1>", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "false");
@ -1607,7 +1617,7 @@ public class DefaultServletTest
{
FS.ensureDirExists(docRoot);
Path index = docRoot.resolve("index.html");
createFile(index, "<h1>Hello World</h1>");
Files.writeString(index, "<h1>Hello World</h1>", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "true");
@ -1883,11 +1893,11 @@ public class DefaultServletTest
{
FS.ensureDirExists(docRoot);
Path data = docRoot.resolve("data.txt");
createFile(data, "01234567890123456789012345678901234567890123456789012345678901234567890123456789");
Files.writeString(data, "01234567890123456789012345678901234567890123456789012345678901234567890123456789", UTF_8);
// test a range request with a file with no suffix, therefore no mimetype
Path nofilesuffix = docRoot.resolve("nofilesuffix");
createFile(nofilesuffix, "01234567890123456789012345678901234567890123456789012345678901234567890123456789");
Files.writeString(nofilesuffix, "01234567890123456789012345678901234567890123456789012345678901234567890123456789", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "false");
@ -1909,9 +1919,9 @@ public class DefaultServletTest
{
FS.ensureDirExists(docRoot);
Path file0 = docRoot.resolve("data0.txt");
createFile(file0, "Hello Text 0");
Files.writeString(file0, "Hello Text 0", UTF_8);
Path image = docRoot.resolve("image.jpg");
createFile(image, "not an image");
Files.writeString(image, "not an image", UTF_8);
server.stop();
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
@ -1994,9 +2004,9 @@ public class DefaultServletTest
{
FS.ensureDirExists(docRoot);
Path file0 = docRoot.resolve("data0.txt");
createFile(file0, "Hello Text 0");
Files.writeString(file0, "Hello Text 0", UTF_8);
Path file0gz = docRoot.resolve("data0.txt.gz");
createFile(file0gz, "fake gzip");
Files.writeString(file0gz, "fake gzip", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "false");
@ -2147,9 +2157,9 @@ public class DefaultServletTest
{
FS.ensureDirExists(docRoot);
Path file0 = docRoot.resolve("data0.txt");
createFile(file0, "Hello Text 0");
Files.writeString(file0, "Hello Text 0", UTF_8);
Path file0gz = docRoot.resolve("data0.txt.gz");
createFile(file0gz, "fake gzip");
Files.writeString(file0gz, "fake gzip", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "false");
@ -2273,8 +2283,8 @@ public class DefaultServletTest
@Disabled
public void testBrotli() throws Exception
{
createFile(docRoot.resolve("data0.txt"), "Hello Text 0");
createFile(docRoot.resolve("data0.txt.br"), "fake brotli");
Files.writeString(docRoot.resolve("data0.txt"), "Hello Text 0", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.br"), "fake brotli", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "false");
@ -2413,8 +2423,8 @@ public class DefaultServletTest
@Disabled
public void testCachedBrotli() throws Exception
{
createFile(docRoot.resolve("data0.txt"), "Hello Text 0");
createFile(docRoot.resolve("data0.txt.br"), "fake brotli");
Files.writeString(docRoot.resolve("data0.txt"), "Hello Text 0", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.br"), "fake brotli", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("dirAllowed", "false");
@ -2538,9 +2548,9 @@ public class DefaultServletTest
@Disabled
public void testDefaultBrotliOverGzip() throws Exception
{
createFile(docRoot.resolve("data0.txt"), "Hello Text 0");
createFile(docRoot.resolve("data0.txt.br"), "fake brotli");
createFile(docRoot.resolve("data0.txt.gz"), "fake gzip");
Files.writeString(docRoot.resolve("data0.txt"), "Hello Text 0", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.br"), "fake brotli", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.gz"), "fake gzip", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("precompressed", "true");
@ -2587,10 +2597,10 @@ public class DefaultServletTest
@Disabled
public void testCustomCompressionFormats() throws Exception
{
createFile(docRoot.resolve("data0.txt"), "Hello Text 0");
createFile(docRoot.resolve("data0.txt.br"), "fake brotli");
createFile(docRoot.resolve("data0.txt.gz"), "fake gzip");
createFile(docRoot.resolve("data0.txt.bz2"), "fake bzip2");
Files.writeString(docRoot.resolve("data0.txt"), "Hello Text 0", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.br"), "fake brotli", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.gz"), "fake gzip", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.bz2"), "fake bzip2", UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
defholder.setInitParameter("precompressed", "bzip2=.bz2,gzip=.gz,br=.br");
@ -2638,10 +2648,10 @@ public class DefaultServletTest
@Disabled
public void testProgrammaticCustomCompressionFormats() throws Exception
{
createFile(docRoot.resolve("data0.txt"), "Hello Text 0");
createFile(docRoot.resolve("data0.txt.br"), "fake brotli");
createFile(docRoot.resolve("data0.txt.gz"), "fake gzip");
createFile(docRoot.resolve("data0.txt.bz2"), "fake bzip2");
Files.writeString(docRoot.resolve("data0.txt"), "Hello Text 0", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.br"), "fake brotli", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.gz"), "fake gzip", UTF_8);
Files.writeString(docRoot.resolve("data0.txt.bz2"), "fake bzip2", UTF_8);
ResourceService resourceService = new ResourceService();
resourceService.setPrecompressedFormats(new CompressedContentFormat[]{
@ -2739,7 +2749,7 @@ public class DefaultServletTest
response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.NOT_FOUND_404));
createFile(file, content);
Files.writeString(file, content, UTF_8);
rawResponse = connector.getResponse("""
GET /context/file.txt HTTP/1.1\r
@ -2812,7 +2822,7 @@ public class DefaultServletTest
@Disabled
public void testIfETag(String content) throws Exception
{
createFile(docRoot.resolve("file.txt"), content);
Files.writeString(docRoot.resolve("file.txt"), content, UTF_8);
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
@ -2927,7 +2937,7 @@ public class DefaultServletTest
// Create file with UTF-8 NFC format
String filename = "swedish-" + new String(StringUtil.fromHexString("C3A5"), UTF_8) + ".txt";
createFile(docRoot.resolve(filename), "hi a-with-circle");
Files.writeString(docRoot.resolve(filename), "hi a-with-circle", UTF_8);
// Using filesystem, attempt to access via NFD format
Path nfdPath = docRoot.resolve("swedish-a" + new String(StringUtil.fromHexString("CC8A"), UTF_8) + ".txt");
@ -2977,7 +2987,7 @@ public class DefaultServletTest
// Create file with UTF-8 NFD format
String filename = "swedish-a" + new String(StringUtil.fromHexString("CC8A"), UTF_8) + ".txt";
createFile(docRoot.resolve(filename), "hi a-with-circle");
Files.writeString(docRoot.resolve(filename), "hi a-with-circle", UTF_8);
// Using filesystem, attempt to access via NFC format
Path nfcPath = docRoot.resolve("swedish-" + new String(StringUtil.fromHexString("C3A5"), UTF_8) + ".txt");
@ -3057,15 +3067,6 @@ public class DefaultServletTest
}
}
private void createFile(Path path, String str) throws IOException
{
try (OutputStream out = Files.newOutputStream(path))
{
out.write(str.getBytes(UTF_8));
out.flush();
}
}
private boolean deleteFile(Path file) throws IOException
{
if (!Files.exists(file))

View File

@ -97,7 +97,6 @@ public class DispatcherTest
_resourceHandler = new ResourceHandler();
Path basePath = MavenTestingUtils.getTestResourcePathDir("dispatchResourceTest");
_resourceHandler.setBaseResource(Resource.newResource(basePath));
_resourceHandler.setPathInfoOnly(true);
ContextHandler resourceContextHandler = new ContextHandler("/resource");
resourceContextHandler.setHandler(_resourceHandler);
_contextCollection.addHandler(resourceContextHandler);