Spring Boot has had support for enabling CORS in REST controllers since version 1.3. The @CrossOrigin
annotation is straightforward to apply at the method or type level to enable cross origin requests:
@SpringBootApplication @RestController @CrossOrigin(origins = "http://localhost:8080") public class App { @PostMapping(path = "/foo", consumes = MediaType.APPLICATION_JSON_VALUE) public String postFoo(@RequestBody String body) { return "Value posted: " + body; } public static void main(String[] args) { SpringApplication.run(App.class, args); } }
Testing with cURL
cURL is an obvious choice for testing CORS with Spring Boot RESTful API endpoints.
$ curl -v -X POST \ -H "Origin: http://localhost:8080" \ -H "Content-Type: application/json" \ -d "{}" \ http://localhost:8080/foo
results in the following output:
* Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to localhost (127.0.0.1) port 8080 (#0) > POST /foo HTTP/1.1 > User-Agent: curl/7.35.0 > Host: localhost:8080 > Accept: */* > Origin: http://localhost:8080 > Content-Type: application/json > Content-Length: 2 > * upload completely sent off: 2 out of 2 bytes < HTTP/1.1 200 < Content-Type: text/plain;charset=UTF-8 < Content-Length: 16 < Date: Thu, 08 Jun 2017 21:23:55 GMT < * Connection #0 to host localhost left intact Value posted: {}
Changing the value of the Origin
header results in the expected HTTP 403 response. Here’s how to test out the CORS preflight OPTIONS
request:
$ curl -v -X OPTIONS \ -H "Access-Control-Request-Method: POST" \ -H "Origin: http://localhost:8080" \ -H "Access-Control-Request-Headers: Content-Type" \ http://localhost:8080/foo
results in the following output:
* Hostname was NOT found in DNS cache * Trying 127.0.0.1... * Connected to localhost (127.0.0.1) port 8080 (#0) > OPTIONS /foo HTTP/1.1 > User-Agent: curl/7.35.0 > Host: localhost:8080 > Accept: */* > Access-Control-Request-Method: POST > Origin: http://localhost:8080 > Access-Control-Request-Headers: Content-Type > < HTTP/1.1 200 < Allow: GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH < Content-Length: 0 < Date: Wed, 07 Jun 2017 21:20:00 GMT < * Connection #0 to host localhost left intact
Testing with Postman
Postman can be a little tricky if you’re using the Chrome extension. This version automatically adds the Origin
header populated with a value like chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
, which can result in a 403 Invalid CORS Request
because it doesn’t match the allowed origins. In this case, the Postman native app is a better choice, because it allows you to edit the Origin
header.
References
1. Spring REST service with CORS example
2. Postman Origin header
3. Understanding CORS
4. CORS support in Spring