spring-projects / spring-boot

Spring Boot
https://spring.io/projects/spring-boot
Apache License 2.0
74.69k stars 40.58k forks source link

Embedded servlet customizer unavailable to management webserver #14302

Open ranarula opened 6 years ago

ranarula commented 6 years ago

I have a custom WebServerFactoryCustomizer but its not available for management webserver. What's the best way to make the customization available to management webserver?

here is the customizer (to disable TRACE for Undertow)

public class UndertowCustomizer implements
  WebServerFactoryCustomizer<ConfigurableUndertowWebServerFactory> {

@Override
public void customize(final ConfigurableUndertowWebServerFactory undertowWebServerFactory) {
  undertowWebServerFactory.addDeploymentInfoCustomizers(deploymentInfo ->
      deploymentInfo.addInitialHandlerChainWrapper(handler ->
          new DisallowedMethodsHandler(handler, HttpString.tryFromString(HttpMethod.TRACE.name())))
  );
 }
}

A reproducible test case is at https://github.com/ranarula/WebServerCustomizer

Filing the ticket based on the discussion with @snicoll & @bclozel on Gitter

philwebb commented 6 years ago

See also #9560 which is a similar issue

philwebb commented 6 years ago

Not sure if this is a dupe of #9560 or not, but something we should certainly consider at the same time. I'll target this to backlog but it might be hard to get to it for 2.1.

ranarula commented 6 years ago

Thanks @philwebb for prioritizing this.

For the time being do you have any suggestions on any workaround on how we can accomplish this. As per the sample we need to disable a few http verbs (TRACE) on all embedded server ports

philwebb commented 6 years ago

do you have any suggestions on any workaround on how we can accomplish this

Not currently I'm afraid.

bclozel commented 6 years ago

I'm also wondering if #4929 isn't linked as well. Some developers expect infrastructure beans in the parent context to act on the management context - others expect the exact opposite.

In some cases we're overriding defaults or picking a restricted set of things from the parent context (like the DispatcherServlet override in WebMvcEndpointChildContextConfiguration, the server setup in ServletManagementChildContextConfiguration). Other issues are also considering a specific ObjectMapper instance for the Actuator parts (#12951), or if custom HandlerMapping should be available (#14012).

Should we try to set up ground rules for these and manage expectations in that space? Applying app customization on actuator and standardizing its behavior across all apps are conflicting goals.

wilkinsona commented 6 years ago

You can customize the separate management server using @ManagementContextConfiguration and an entry in spring.factories. Something like this:

package com.example.demo;

import org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;

import io.undertow.server.handlers.DisallowedMethodsHandler;
import io.undertow.util.HttpString;

@ManagementContextConfiguration
public class ManagementContextCustomization {

    @Bean
    public WebServerFactoryCustomizer<UndertowServletWebServerFactory> undertowCustomizer() {
        return (factory) -> {
            factory.addDeploymentInfoCustomizers(deploymentInfo ->
                deploymentInfo.addInitialHandlerChainWrapper(handler ->
                    new DisallowedMethodsHandler(handler, HttpString.tryFromString(HttpMethod.TRACE.name()))));
        };
    }

}

spring.factories:

org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration=com.example.demo.ManagementContextCustomization

IIRC, @ManagementContextConfiguration is no longer documented as we want it to become an implementation detail so this is really just a workaround. I agree with Brian though that we need a better, more formalised way of controlling what customisation applies to the main server and what applies to the separate management server if there is one.