web-dev-qa-db-fra.com

Comment gérer les requêtes HTTP OPTIONS dans Spring Boot?

Tout d’abord, j’ai lu " Comment gérer les options HTTP avec Spring MVC? " mais les réponses ne semblent pas directement applicables à Spring Boot.

Il semble que je devrais faire ceci:

configurez le dispatcherServlet en définissant son dispatchOptionsRequest à true

Mais comment faire cela, étant donné que je n'ai aucune configuration XML, ni aucune variété de la classe d'initialisation DispatcherServlet dans mon code ( mentionné par cette réponse )?

Dans une classe @RestController, j'ai une méthode comme celle-ci, qui n'est actuellement pas invoquée.

@RequestMapping(value = "/foo", method = RequestMethod.OPTIONS)
public ResponseEntity options(HttpServletResponse response) {
    log.info("OPTIONS /foo called");
    response.setHeader("Allow", "HEAD,GET,PUT,OPTIONS");
    return new ResponseEntity(HttpStatus.OK);
}

Botte à ressort 1.2.7.RELEASE; une configuration simple pas très différente de celle de Guide Spring REST .

22
Jonik

Option 1: Propriétés de Spring Boot (Spring Boot 1.3.0+ uniquement)

À partir de Spring Boot 1.3.0, ce comportement peut être configuré à l'aide de la propriété suivante:

spring.mvc.dispatch-options-request=true

Option 2: Personnalisé DispatcherServlet

DispatcherServlet dans Spring Boot est défini par DispatcherServletAutoConfiguration. Vous pouvez créer votre propre bean DispatcherServlet quelque part dans vos classes de configuration, qui seront utilisées à la place de celui de la configuration automatique:

@Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet() {
    DispatcherServlet dispatcherServlet = new DispatcherServlet();
    dispatcherServlet.setDispatchOptionsRequest(true);
    return dispatcherServlet;
}

Sachez toutefois que la définition de votre bean DispatcherServlet désactive la configuration automatique. Vous devez donc définir manuellement les autres beans déclarés dans la classe de configuration automatique, à savoir le ServletRegistrationBean pour DispatcherServlet.

Option 3: BeanPostProcessor

Vous pouvez créer une implémentation BeanPostProcessor qui définira l'attribut dispatchOptionsRequest sur true avant l'initialisation du bean. Yoy peut mettre cela quelque part dans vos classes de configuration:

@Bean
public DispatcherServletBeanPostProcessor dispatcherServletBeanPostProcessor() {
    return new DispatcherServletBeanPostProcessor();
}

public static class DispatcherServletBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof DispatcherServlet) {
            ((DispatcherServlet) bean).setDispatchOptionsRequest(true);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

Option 4: SpringBootServletInitializer

Si vous aviez SpringBootServletInitializer dans votre application, vous pourriez faire quelque chose comme ceci pour activer l'envoi d'OPTIONS:

public class ServletInitializer extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        super.onStartup(servletContext);
        servletContext.getServletRegistration(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
                .setInitParameter("dispatchOptionsRequest", "true");
    }
}

Cela ne fonctionnerait cependant que si vous déployiez votre application en tant que fichier WAR dans le conteneur Servlet, car le code SpringBootServletInitializer n'est pas exécuté lors de l'exécution de votre application Spring Boot à l'aide de la méthode main.

21
Bohuslav Burghardt

Je rencontrais ce problème avec une application de repos basée sur Spring Boot 1.3.x et tout en diagnostiquant le problème, j’autorisais ma suite Spring Tool à mettre à jour vers la dernière version. 

Lorsque j'ai créé un nouveau test Spring Boot RestController dans le STS mis à jour, il fonctionnait de la même manière que la documentation l'annonce sous Spring 4.3. J'ai remarqué que la dépendance Maven avait sauté à la botte printanière 1.5.8 dans la nouvelle application de test, alors je viens de changer la dépendance de l'ancienne application pour la mettre à jour à la botte printanière 1.5.8/spring 4.3.12. Cela a résolu le problème et maintenant cela fonctionne comme annoncé avec une annotation RequestMapping spécifiant un intérêt pour le traitement des demandes OPTIONS ...

@RequestMapping(value="/account/{id}", method={RequestMethod.OPTIONS,RequestMethod.GET})

... envoie maintenant la demande OPTIONS au gestionnaire.

Ainsi, si vous pouvez mettre à jour une version ultérieure de Spring, vous ne devriez pas avoir besoin de définir de configuration spéciale pour activer le traitement de la méthode de requête OPTIONS (Spring 4.3.12/Spring Boot 1.5.8).

0
beaudet