1

I have a rest-controller(SPRINGBOOT) with custom 'OPTIONS' method implemented. The problem is: when i make an ajax call to this 'OPTIONS' method, I get two responses one by default and the other from the implemented one. Where is the second response coming from. If it is from the default handling of 'OPTIONS' method in SPRINGBOOT, how to disable it ?

My Rest Controller looks like this:

@RestController
public class FetchOnPremData {

    @RequestMapping(value = "/fetchData/{jiraid}", method = RequestMethod.OPTIONS)
    public int options(@PathVariable String jiraid ,HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Methods","GET,HEAD,POST");
        response.setHeader("Allow", "HEAD,GET,PUT,OPTIONS");
        response.setHeader("Access-Control-Allow-Origin","*");
        return 234;
    }
}

AJAX call made by me looks like this:

   $.ajax({

    type: 'OPTIONS',
    context: this,
      url: "https://myserverurl/fetchData/CFNDGEMINI-128",
      success: function(oResponseStatus, xhr) 
    {if (oResponseStatus === 234) {
console.log("valid");}
     else {
    console.log("invalid");                                                                                   
    }

EDIT: How to handle HTTP OPTIONS requests in Spring Boot?

this question addresses the problem of OPTIONS method not being invoked. In my case, OPTIONS method is working but another OPTIONS method is also giving a response. My question is asking about where the other response is coming from.

codemania23
  • 913
  • 11
  • 19
  • Possible duplicate of [How to handle HTTP OPTIONS requests in Spring Boot?](https://stackoverflow.com/questions/33331042/how-to-handle-http-options-requests-in-spring-boot) – Ori Marko Jan 03 '18 at 11:56

1 Answers1

2

First Request must be generated by your browser by default as a contract of CORS. This request is addressed by Spring's CORS Processor due to the presence of preflight headers.

If Spring allows it by sending proper Headers then browser will generate your actual request which will be addressed by your rest controller. Now if you still want to handle preflight request by yourself then you must extend CORSConfiguration class and override its methods.

Note: - Even if you do this then also your browser will raise two request. First will be addressed by your custom overridden methods and second by your controller. In general there is no need to define controller for OPTIONS as you will not need OPTIONS request in your application. It is automatically raised by browser if required[as per CORS Contract] and it will be handled by springs CORS Processor.

Configuring CORS (If you are not using Spring-security module) :
There are 3 ways

  1. Using annotaion @Crossorigin [per rest-api or per rest controller basis]

  2. Using Global CORS Configuration

  3. Extending CorsFilter

Way 1 (@CrossOrigin) This annotation can be applied to either class or on method. example :--

@RestController
@CrossOrigin(origins = {"http://localhost:8585"}, maxAge = 4800, allowCredentials = "false")
public class FetchOnPremData {

    @RequestMapping(value = "/fetchData/{jiraid}", method = RequestMethod.OPTIONS)
    public int options(@PathVariable String jiraid ,HttpServletResponse response) {
        response.setHeader("Access-Control-Allow-Methods","GET,HEAD,POST");
        response.setHeader("Allow", "HEAD,GET,PUT,OPTIONS");
        response.setHeader("Access-Control-Allow-Origin","*");
        return 234;
    }
}

or on method :

@RestController
public class FetchOnPremData {

    @CrossOrigin
    @RequestMapping(value = "/fetchData/{jiraid}", method = RequestMethod.GET)
    public int options(@PathVariable String jiraid ,HttpServletResponse response) {
// your code
        return 234;
    }

Way 2 : Global Cors Configuration If you want to enable cors support for all of your rest controllers then use this option.

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
        .allowedOrigins("http://domain2.com")
        .allowedMethods("PUT", "DELETE")
            .allowedHeaders("header1", "header2", "header3")
        .exposedHeaders("header1", "header2")
        .allowCredentials(false).maxAge(3600);
    }
}

Way 3 : Using CorsFilter

If you want greater control then you can can prefer this.

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {


    // This bean will override default cors filter 
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

Configuring CORS (If you are using Spring-Security module) :

Then in addition to using any of the above mentioned ways you will have to add the following to your configuration :

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors().and()
            ...
    }
}

references :
Spring Security CORS Configuration documentation
Spring MVC CORS Configuration documentation