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?
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)
}
}
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')
Access-Control-Allow-Origin
should contain exact domain name (btw, for some browsers '*'
works as well), jsbin.com
at your case.