The backend is developed by Spring MVC and hosted in tomcat.
When I use postman dev tool in Chrome to test the endpoint (Restful), everything is working fine. The "Access-Control-Allow-Origin", "*" is successfully added in the server. like below screenshot
But when I wrote the Ajax to make the same request. Because browser has the Origin Policy (postman has no this policy), it will first send an HTTP OPTIONS request header to the server to determine whether the actual request is safe to send. like below screenshot.
The response header is quite different to the one I got from postman, and there is no "Access-Control-Allow-Origin", "*" in the header. I think the server just can't accept the options request.
I have tried to add the filter in tomcat web.xml by looking this link: http://enable-cors.org/server_tomcat.html
It's Only working perfectly by using dev tool like curl and postman which has no Origin policy. But it's not working on the browser by Ajax.
Please see the below filter class
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
System.out.println("test123");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {}
public void destroy() {}
}
I use the System.out.println("test123");
in the filter, when using postman or curl, it printed the 'test123' in the console, but didn't print when using browser, so I guess the browser send the OPTIONS request, and the filter didn't intercept it, or other things intercept the request from browser first?
Can anyone help me please? Thanks.
If you are using tomcat you can have tomcat's implementaion in your web.xml:
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Or In my application I did a filter(updated) like below:
public class CorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, HEAD, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
if ("OPTIONS".equalsIgnoreCase((HttpServletRequest) servletRequest.getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(servletRequest, response);
}
}
@Override
public void destroy() {
}
}
Also please note that you should not annotate filter class with Spring's annotations like @Component
Or better you can go with Spring's CORS support
Using an response.setHeader("Access-Control-Allow-Origin", "*");
Will not work.
You will need to put the explicit requesting URL.
Take the origin from the request to the servlet and dynamically replace on each request.
Here's a code snippet that I use to solve this problem:
String clientOrigin = request.getHeader("origin");
response.setHeader("Access-Control-Allow-Origin", clientOrigin);
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Access-Control-Allow-Origin,CopyStreamException,Access-Control-Allow-Methods,Access-Control-Max-Age");
EDIT 1:
I've looked at my code again, and I saw that I also added filters to my web.xml as mentioned by @Tom-Sebastian
Here what I have in the web.xml:
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<servlet-name>myServlet</servlet-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Hope it will help,
Liron