I try to enable directory listing in Spring Boot v2.7.0 with embedded Jetty by implementing a WebServerFactoryCustomizer:
public class MyJettyWebServerCustomizer implements WebServerFactoryCustomizer<JettyServletWebServerFactory> {
@Override
public void customize(JettyServletWebServerFactory factory) {
JettyServerCustomizer jettyServerCustomizer = new JettyServerCustomizer() {
@Override
public void customize(Server server) {
Handler[] childHandlersByClass = server.getChildHandlersByClass(WebAppContext.class);
final WebAppContext webAppContext = (WebAppContext) childHandlersByClass[0];
ServletHandler handler = webAppContext.getServletHandler();
ServletHolder defServlet = ((WebAppContext)server.getHandlers()[0]).getServletHandler().getServlets()[0];
defServlet.setInitParameter("dirAllowed","true");
defServlet.setInitParameter("resourceBase","/tmp/");
webAppContext.getServletHandler().addServletWithMapping(defServlet, "/foo");
webAppContext.getServletHandler().getServletMapping("/foo").setDefault(true);
}
};
factory.addServerCustomizers(jettyServerCustomizer);
}
}
But requesting http://localhost:8080/foo
returns a 404. Creating a new Default Servlet does also not work:
ServletHolder holder = new ServletHolder();
holder.setName("default");
holder.setClassName("org.eclipse.jetty.servlet.DefaultServlet");
holder.setInitParameter("dirAllowed", "true");
holder.setInitOrder(1);
webAppContext.getServletHandler().addServletWithMapping(holder, "/foo");
webAppContext.getServletHandler().getServletMapping("/foo").setDefault(true);
Did I fundamentally misunderstand something or did I miss something else like another configuration?
CodePudding user response:
Don't use ...
webAppContext.getServletHandler().addServletWithMapping(defServlet, "/foo");
webAppContext.getServletHandler().getServletMapping("/foo").setDefault(true);
That has 2 problems.
The ServletHandler is an internal class, and is not meant to be manipulated like that, especially after the WebAppContext has been started.
Use the
WebAppContext
directly if you can (I don't know what state of initialization that particularWebAppContext
is in).The mapping for
DefaultServlet
MUST be a url-pattern with a prefix-match type mapping.
The replacement for those 2 lines would be ...
webAppContext.addServlet(defServlet, "/foo/*");
But wait! there's more!
You cannot re-use the existing DefaultServlet
like that (changing the configuration, such as resourceBase
would break the servlet spec standard DefaultServlet
behavior in a bad way)
Create a new one, map it to /foo/*
(be careful of the pathInfoOnly
init param, as it might prove useful to your setup)