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 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?
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. 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?
Share Improve this question asked Apr 3, 2012 at 19:54 Stefan KendallStefan Kendall 67.9k69 gold badges258 silver badges409 bronze badges 1- Two things e 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 Commented Apr 4, 2012 at 13:23
3 Answers
Reset to default 2It 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>.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 remend 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.
at your case.