Info

Spring Boot version: 3.3.3/3.3.4

Description

spring-boot-starter-jetty does not handle the TRACE HTTP method as spring-boot-starter-tomcat does.

As per my tests, I see the following scenarios: - Tomcat blocks the TRACE method no matter the port - Jetty allows the TRACE method by default on either the server port or management port - Jetty with a custom DispatcherServlet returns 405 on the server port and 200 on the management port

Custom DispatcherServlet:

public class CustomDispatcherServlet extends DispatcherServlet {

    @Override
    protected void doTrace(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("TRACE IS NOT ALLOWED");
        response.sendError(SC_METHOD_NOT_ALLOWED);
    }
}

I built this simple project to replicate the issue.

Comment From: wilkinsona

The behaviour that you have described is to be expected as Tomcat and Jetty have different default behavior in this area. The differences between the different embedded servers are one reason why we offer support for Jetty and Undertow in addition to Tomcat as one container may be a better fit for an application's needs than another.

When you configure a custom dispatcher servlet, the management server on a separate port continues to respond with 200 as it's using a separate dispatcher servlet.

You may find this Q&A on Stack Overflow helpful in learning how to customize Jetty's configuration. You can apply that sort of customization in a Spring Boot app using a JettyServerCustomizer bean:

@Bean
JettyServerCustomizer jettyServerCustomizer() {
    return (server) -> {
        ServletContextHandler servletContextHandler = findServletContextHandler(server);
        // Customize handler to disable TRACE support
    };
}

private static ServletContextHandler findServletContextHandler(Container container) {
    for (Handler handler : container.getHandlers()) {
        if (handler instanceof ServletContextHandler servletContextHandler) {
            return servletContextHandler;
        }
        if (handler instanceof Container containerHandler) {
            ServletContextHandler servletContextHandler = findServletContextHandler(containerHandler);
            if (servletContextHandler != null) {
                return servletContextHandler;
            }
        }
    }
    return null;
}

Alternatively, you may want to use Tomcat if its defaults are a better match for your needs and expectations.

If you have any further questions, please follow up on Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.

Comment From: bu3

Thanks for the quick reply @wilkinsona. I thought it was a bug since my application running on Spring Boot 2 and Jetty 9 was working fine. When I moved the code to SB3 the same configuration won't work and the management server seems to be ignoring any kind of customization and always returning 200.

I can extend my test project if you want with the code snipped you shared above

Comment From: wilkinsona

Jetty's behavior may well have changed between 9 and 12. Thanks for the offer, but there's no need to extend your test project from my perspective as I don't think this is a Spring Boot problem.

Comment From: bu3

Even if I show you it has the same issue using JettyServerCustomizer and Jetty 12? I managed to create a Jetty constraint for TRACE using the customizer but it gets applied to the main server only. Mgmt server keeps responding with 200. I have no clue what Spring boot does under the hood to start two different servers. Could not that be a bug?

Comment From: wilkinsona

When using a separate port there's a separate Jetty instance running in the management context. You can use @ManagementContextConfiguration to declare beans that should be applied to that context.

Comment From: bu3

Exactly. That's what I thought as well. I used that Annotation here and the same logic in the main class.

Still not working but this time instead of returning 405 on the server port it returns 403. While MgmtServer keeps returning a 200

Server

Expected: <405 METHOD_NOT_ALLOWED>
     but: was <403 FORBIDDEN>
Expected :<405 METHOD_NOT_ALLOWED>
Actual   :<403 FORBIDDEN>

MgmtServer

Expected: <405 METHOD_NOT_ALLOWED>
     but: was <200 OK>
Expected :<405 METHOD_NOT_ALLOWED>
Actual   :<200 OK>

Comment From: wilkinsona

You're not using @ManagementContextConfiguration correctly. As described in the javadoc, it needs to be registered in a /META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports file. It also shouldn't be in a package that's covered by component scanning.

I'm afraid the issue tracker isn't the right place for this sort of support. If you have any further questions, please follow up on Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.

Comment From: bu3

Done. Just posted in there. Sorry if I bothered you

Comment From: bu3

In case anybody arrives here, this is my Stack Overflow post

Comment From: bu3

I managed to make this work using WebServerFactoryCustomizer<JettyServletWebServerFactory> instead of JettyServerCustomizer

@Bean
    WebServerFactoryCustomizer<JettyServletWebServerFactory> disableTrace() {
        return (factory) -> {
            factory.addServerCustomizers((server) -> {
                ServletContextHandler servletContextHandler = findServletContextHandler(server);
                disableTraceMethodForHandler(servletContextHandler);
            });
        };
    }

More details in this StackOverflow post