How to enable CORS in Grails 3.0.1

后端 未结 7 1338
有刺的猬
有刺的猬 2021-02-18 22:45

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 thi

相关标签:
7条回答
  • 2021-02-18 22:53

    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.

    0 讨论(0)
  • 2021-02-18 22:53

    You should use grails 3's new Interceptor API. (https://grails.github.io/grails-doc/3.0.x/guide/single.html#interceptors)

    You can create an interceptor with the grails create-interceptor command. For a CORS Interceptor I would use the after() method of this Interceptor, and set it up to match all requests (or just the requests you need). You can use the response object in this method, so setting the headers should be similar to the case described in the Spring documentation.

    0 讨论(0)
  • 2021-02-18 22:55

    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

    0 讨论(0)
  • 2021-02-18 23:00

    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.

    0 讨论(0)
  • 2021-02-18 23:02

    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 }
    }
    
    0 讨论(0)
  • 2021-02-18 23:08

    The cleanest and simplest solution for grails 3.1.x I found is to add the Apache default CorsFilter:

    import org.apache.catalina.filters.CorsFilter
    
    // Place your Spring DSL code here
    beans = {
        corsFilter(CorsFilter) //Custom CorsFilter under src/main/java/ works as well. I prefer Apache though...
    }
    

    The answer from #user215556 works as well but the default setting of the Apache Cors filter is ok as well

    0 讨论(0)
提交回复
热议问题