How to handle HTTP OPTIONS with Spring MVC?
Asked Answered
S

5

28

I'd like to intercept the OPTIONS request with my controller using Spring MVC, but it is catched by the DispatcherServlet. How can I manage that?

Subsequent answered 1/3, 2012 at 18:20 Comment(1)
For those on Spring Boot, this follow-up question may be useful: #33331542Gaberones
P
12
@RequestMapping(value="/youroptions", method=RequestMethod.OPTIONS)
public View getOptions() {

}

You should configure the dispatcherServlet by setting its dispatchOptionsRequest to true

Pampas answered 1/3, 2012 at 18:21 Comment(3)
actually it won't work since the DispatcherServlet will intercept the request and it will handle it. It should be configured the DispatcherServlet instead. I had a lot of pain with this issue, and currently I partially solved the problem. I wanted to post my solution for the community but... since I have less than 100 of reputation stackoverflow force me to wait 8 hours befor letting me answer my own questions.Subsequent
yes it is the solution. I should have met you before, good god! XD However this is a "partial" solution because the DispatcherServlet will do "some work" before delegating your controller. Infact, even though you won't touch the "Allow" header it will be filled with a list of "allowed method". In my case it wouldn't be a problem but I suppose it is for someone else.Subsequent
Important update: OPTIONS requests will be supported by default as of Spring Framework 4.3, see jira.spring.io/browse/SPR-13130 for more details.Precessional
S
34

I added some more detail to the Bozho answer for beginners. Sometimes it is useful to let the Spring Controller manage the OPTIONS request (for example to set the correct "Access-Control-Allow-*" header to serve an AJAX call). However, if you try the common practice

@Controller
public class MyController {

    @RequestMapping(method = RequestMethod.OPTIONS, value="/**")
    public void manageOptions(HttpServletResponse response)
    {
        //do things
    }
}

It won't work since the DispatcherServlet will intercept the client's OPTIONS request.

The workaround is very simple:

You have to... configure the DispatcherServlet from your web.xml file as follows:

...
  <servlet>
    <servlet-name>yourServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>dispatchOptionsRequest</param-name>
      <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
...

Adding the "dispatchOptionsRequest" parameter and setting it to true.

Now the DispatcherServlet will delegate the OPTIONS handling to your controller and the manageOption() method will execute.

Hope this helps.

PS. to be honest, I see that the DispatcherServlet append the list of allowed method to the response. In my case this wasn't important and I let the thing go. Maybe further examinations are needed.

Subsequent answered 2/3, 2012 at 8:45 Comment(1)
but this does not work, if for example a handlermethod is registered at endpoint "/x/y". Now an OPTIONS-request to /x works but not to /x/y is there any option to solve this issue? meaning to add this OPTIONS-handling to all of the registered endpoints? I think about interceptors but is there any other way?Melbamelborn
P
12
@RequestMapping(value="/youroptions", method=RequestMethod.OPTIONS)
public View getOptions() {

}

You should configure the dispatcherServlet by setting its dispatchOptionsRequest to true

Pampas answered 1/3, 2012 at 18:21 Comment(3)
actually it won't work since the DispatcherServlet will intercept the request and it will handle it. It should be configured the DispatcherServlet instead. I had a lot of pain with this issue, and currently I partially solved the problem. I wanted to post my solution for the community but... since I have less than 100 of reputation stackoverflow force me to wait 8 hours befor letting me answer my own questions.Subsequent
yes it is the solution. I should have met you before, good god! XD However this is a "partial" solution because the DispatcherServlet will do "some work" before delegating your controller. Infact, even though you won't touch the "Allow" header it will be filled with a list of "allowed method". In my case it wouldn't be a problem but I suppose it is for someone else.Subsequent
Important update: OPTIONS requests will be supported by default as of Spring Framework 4.3, see jira.spring.io/browse/SPR-13130 for more details.Precessional
U
8

As a quick supplement to the above 2 answers, here's how to enable dispatchOptionsRequest in a servlet 3 (no web.xml) environment as it took me a while to work out how to apply the answers above in a non-xml setup.

In a spring 3.2 / servlet 3 environment, you will have some variety of DispatcherServlet initializer class which is the java equivalent of web.xml; in my case it's the AbstractAnnotationConfigDispatcherServletInitializer. Adding the following code will enable dispatchOptionsRequest:

    @Override
    protected void customizeRegistration(Dynamic registration) {
        registration.setInitParameter("dispatchOptionsRequest", "true");
    }
Unfurl answered 2/4, 2013 at 10:23 Comment(0)
M
4

I took the following approach:

Using Maven (or manually) pull in this dependancy:

<dependency>
    <groupId>com.thetransactioncompany</groupId>
    <artifactId>cors-filter</artifactId>
    <version>1.3.2</version>
</dependency>

This has an implementation to capture all the inbound OPTIONS requests. Into the web.xml file add the following config:

<filter>
   <filter-name>CORS</filter-name>
   <filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>       
   <init-param>
      <param-name>cors.supportedHeaders</param-name>
      <param-value>Content-Type,Accept,Origin</param-value>
   </init-param>
</filter>

<filter-mapping>
   <filter-name>CORS</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

The problem I've seen with the /** approach is a more specific Controller implementation will override this.

Modigliani answered 15/4, 2013 at 18:17 Comment(0)
L
0

For Spring without web.xml file, and based on Paul Adamson answer, I just set the parameter dispatchOptionsRequest to true into the dispatcher, to process the Options method calls.

ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new        DispatcherServlet(applicationContext));

dispatcher.setInitParameter("dispatchOptionsRequest", "true");                

dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
Lashawn answered 3/1, 2015 at 21:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.