I am trying to configure CORS globally via WebMvcConfigurerAdapter
shown below. To test I am hitting my API endpoint via a small node app I created to emulate an external service. When I try this approach the response does not contain the correct headers and fails with
XMLHttpRequest cannot load http://localhost:8080/api/query/1121. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:333' is therefore not allowed access.
Global Config
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/query/**")
.allowedOrigins("*")
.allowedHeaders("*")
.allowCredentials(true);
}
}
However when I utilize the @CrossOrigin
annotation like so it works just fine responding with the proper headers.
@CrossOrigin(origins = "*", allowCredentials = "true", allowedHeaders = "*")
@RestController
@RequestMapping(value = "/api/query", produces = MediaType.APPLICATION_JSON_VALUE)
public class QueryController {
......
}
Produces
Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin:http://localhost:333
What am I missing to make the global config work (followed instructions here https://spring.io/blog/2015/06/08/cors-support-in-spring-framework). I feel like I'm missing something simple since annotating the controller works just fine.
In order for the global CORS config to work, the client must add these two headers in the OPTIONS request.
Origin: http://host.com
Access-Control-Request-Method: POST
However the @CrossOrigin annotation requires just the "Origin" header.
Your client probably adds the "Origin" header but is missing the "Access-Control-Request-Method".....thats why it works for you with the @CrossOrigin, but doesn't with the global config.
you didn't declared method in it which is by default accept only get method.
try registry.allowedMethods("*");
I was able to get the Spring Global CORS configuration to work, after experiencing the exact problem documented in this issue. I had to do 2 things:
allowedOrigins cannot be * if allowCredentials is true. This is documented at Mozilla.org
Remove mvc:annotation-driven from the spring XML. Cannot have BOTH the XML config and @EnableWebMvc. The global class won't work without @EnableWebMvc, thus mvc:annotation-driven must be removed.
I faced similar issue. I changed the WebMvcConfigurerAdapter to WebMvcConfigurationSupport and it started working.
In addition to this I also moved the RequestMappingHandlerMapping defined in xml configuration file to java configuration.
I think your mapping definition is missing a *
:
registry.addMapping("/api/query/**")
Without that extra *
, this configuration is not mapped to the /api/query/1121
request path (but it would work on /api/query/5
).
I had a similar issue and none of methods seemed to work (except using @CrossOrigin
annotation for each controller). I followed Bharat Singh's solution above and after some debugging of Spring Framework internals - here's what worked for me (Spring Boot 2.0.6 + Spring Framework 5.0.10):
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
/* (non-Javadoc)
* @see org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#addCorsMappings(org.springframework.web.servlet.config.annotation.CorsRegistry)
*/
@Override
protected void addCorsMappings(CorsRegistry registry) {
//NOTE: servlet context set in "application.properties" is "/api" and request like "/api/session/login" resolves here to "/session/login"!
registry.addMapping("/**")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedOrigins("*")
.allowedHeaders("*")
.allowCredentials(false);
}
}
Initially when I used "/api/**"
mapping it was configured within Spring, but since the application was deployed with "/api"
context - requests like "/api/session/login"
were internally mapped to "/session/login"
and such mapping in CORS configuration was not found - please pay attention to that!