Home > database >  Directory listing with embedded Jetty and Spring Boot
Directory listing with embedded Jetty and Spring Boot

Time:06-13

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.

  1. 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 particular WebAppContext is in).

  2. 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)

  • Related