How to enable CORS in Grails 3.0.1
I would like to do cross origin communication using Grails in server side. The only documentation that I found is this one
https://grails.org/plugin/cors
but this is for an old version of Grails. The other documentation that I found is for spring:
https://spring.io/guides/gs/rest-service-cors/
so I added the file SimpleCorsFilter.groovy
to init/myproject/
folder, but I don't know how to wire this component into resources.groovy
Solution 1:
So, if you got here using grails 3.2.+ you can use the default way.
Go to your application.yml
and add:
grails:
cors:
enabled: true
It will add Access-Control-Allow-Origin '*'
.
If you want something different, look this page
Solution 2:
We used a normal servlet filter with an entry in resources.groovy to solve this problem:
public class CorsFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain)
throws ServletException, IOException {
String origin = req.getHeader("Origin");
boolean options = "OPTIONS".equals(req.getMethod());
if (options) {
if (origin == null) return;
resp.addHeader("Access-Control-Allow-Headers", "origin, authorization, accept, content-type, x-requested-with");
resp.addHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS");
resp.addHeader("Access-Control-Max-Age", "3600");
}
resp.addHeader("Access-Control-Allow-Origin", origin == null ? "*" : origin);
resp.addHeader("Access-Control-Allow-Credentials", "true");
if (!options) chain.doFilter(req, resp);
}
}
resources.groovy:
beans = {
corsFilter(CorsFilter)
}
This works with CORS requests using basic authentication. I wrote the Grails 2.x plugin and this seemed easier than getting it to work with Grails 3.
Solution 3:
To be specific, here is some code that works. Notice the interceptor name must match your controller name (here, workRequest), the domain needs to be whatever you are calling from (here, localhost:8081) and it is the before() method you want:
package rest
class WorkRequestInterceptor {
boolean before() {
header( "Access-Control-Allow-Origin", "http://localhost:8081" )
header( "Access-Control-Allow-Credentials", "true" )
header( "Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE" )
header( "Access-Control-Max-Age", "3600" )
true
}
boolean after() { true }
}
Solution 4:
I was playing around with the emberjs framework together with a Grails 3.0 rest application when I was hit by the CORS issue. Following the steps in this article http://www.greggbolinger.com/rendering-json-in-grails-for-ember-js/ helped me get further.
The article shows how you can use the new Interceptors to create a CorsInterceptor class which sets the correct headers.
class CorsInterceptor {
CorsInterceptor() {
matchAll()
}
boolean before() {
header( "Access-Control-Allow-Origin", "http://localhost:4200" )
header( "Access-Control-Allow-Credentials", "true" )
header( "Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
header( "Access-Control-Max-Age", "3600" )
true
}
boolean after() { true }
}
This worked as expected for GET requests, but failed for POST and PUT requests. The reason for this was that an OPTIONS preflight request was sent first to http://localhost:8080/mycontroller/1234, which in my case caused a 404 not found to be returned.
With the help from this answer https://stackoverflow.com/a/31834551 I modified the CorsInterceptor class to this instead:
class CorsInterceptor {
CorsInterceptor() {
matchAll()
}
boolean before() {
header( "Access-Control-Allow-Origin", "http://localhost:4200" )
boolean options = ("OPTIONS" == request.method)
if (options) {
header( "Access-Control-Allow-Origin", "http://localhost:4200" )
header( "Access-Control-Allow-Credentials", "true" )
header( "Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
header( "Access-Control-Max-Age", "3600" )
response.status = 200
}
true
}
boolean after() { true }
}
Now POST and PUT requests were working.