CORS in grails - All requests fail?

Go To StackoverFlow.com

5

I'm trying to setup CORS support in grails, and I'm using the following filter:

class CorsFilters {
    def filters = {
        all(controller:'*', action:'*') {
            before = {
                response.setHeader("Access-Control-Allow-Origin", "*")
            }
        }
    }
}

From testing, it looks like the response header is set properly for all requests, but when I make a request externally against localhost or some server available to me, I get the following error:

XMLHttpRequest cannot load http://server:8080. Origin http://jsbin.com is not allowed by Access-Control-Allow-Origin.

This live example works in my instance of Chrome, so I don't know what could be happening here. In the requests that fail, I'm trying to hit tomcat directly.

What could be happening to cause this to fail?

2012-04-03 19:54
by Stefan Kendall
Two things come to mind. 1. Using localhost (a first level domain) is not a good idea; I can't find the source right now, but I had trouble not long ago with this. Use your hosts file to setup a fake host. 2. Is the code in JSBin actually what you're using for the request? If not, some JS libraries/frameworks might send an OPTIONS (pre-flighted) request first, which you need to respond appropriately. Confirm if this is the case and I can provide a response, I've already developed a solution in Grails. Good luck - Esteban 2012-04-04 13:23


2

It looks like Grails Filters, by default, run too late in the filter chain to be of use.

If you generate the web.xml template and add a filter beneath sitemesh, this works.

<filter>
    <filter-name>CORSFilter</filter-name>
    <filter-class>com.blah.CorsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>CORSFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

and

class CorsFilter implements Filter {
    public void init(FilterConfig fConfig) throws ServletException { }

    public void destroy() { }

    public void doFilter(
            ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        ((HttpServletResponse) response).addHeader(
                "Access-Control-Allow-Origin", "*"
        )
        chain.doFilter(request, response)
    }
}
2012-04-03 20:31
by Stefan Kendall
I wrote a Grails plugin to do this: http://grails.org/plugin/cor - David Tinker 2012-09-28 13:59
Just edit BuildConfig.groovy: plugins { runtime ":cors:1.0.0" ... - David Tinker 2012-09-28 14:01


1

You can set the origin dynamically. I also recommend to add the whole set of headers when applies.

response.setHeader('Access-Control-Allow-Origin', request.getHeader("Origin"))
response.setHeader('Access-Control-Allow-Methods', 'POST, PUT, GET, OPTIONS, PATCH')
response.setHeader('Access-Control-Allow-Headers', 'X-Additional-Headers-Example')
response.setHeader('Access-Control-Allow-Credentials', 'true')
response.setHeader('Access-Control-Max-Age', '1728000')
2012-04-03 23:58
by pablomolnar
Why is this good or necessary - Stefan Kendall 2012-04-04 14:29


0

Access-Control-Allow-Origin should contain exact domain name (btw, for some browsers '*' works as well), jsbin.com at your case.

2012-04-03 20:07
by Igor Artamonov
A wildcard, * is also a perfectly valid value - see [spec] - Rob W 2012-04-03 20:11
Yes, I know. But browsers don't care about spec - Igor Artamonov 2012-04-04 05:21