Cross-Origin Request Blocked Spring REST service + AJAX

My AJAX call and service were OK. After searching a lot on internet i have found that its server side problem not client side.

on server side with Spring we have to implement filter which will allow CORS requests.

filter will look like this.

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.filter.OncePerRequestFilter;

public class CORSFilter extends OncePerRequestFilter {
    private static final Log LOG = LogFactory.getLog(CORSFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        response.addHeader("Access-Control-Allow-Origin", "*");
        if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
            LOG.trace("Sending Header....");
            // CORS "pre-flight" request
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
            // response.addHeader("Access-Control-Allow-Headers", "Authorization");
            response.addHeader("Access-Control-Allow-Headers", "Content-Type");
            response.addHeader("Access-Control-Max-Age", "1");
        }
        filterChain.doFilter(request, response);
    }

}

and in web.xml apply this filter on your service requests like this

    <filter>
        <filter-name>cors</filter-name>
        <filter-class>com.test.common.controller.CORSFilter</filter-class> <!-- your package name and filter class -->
    </filter>
    <filter-mapping>
        <filter-name>cors</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping> 

This may help someone else who went through this problem. :)


By default the only method allowed is a GET, and you don't allow the POST on your server side:

Access-Control-Allow-Origin: *

This header only enables CORS, but you need to add this:

Access-Control-Allow-Methods: POST, GET

More detailed how-to about the HTTP access control (CORS) on Mozilla project

So your code should be something like this:

responseHeaders.add("Access-Control-Allow-Methods", "POST, GET"); // also added header to allow POST, GET method to be available
responseHeaders.add("Access-Control-Allow-Origin", "*"); // also added header to allow cross domain request for any domain

Update:

I have re-read the article, and found out some details:

A simple cross-site request is one that:

  • Only uses GET, HEAD or POST. If POST is used to send data to the server, the Content-Type of the data sent to the server with the HTTP POST request is one of application/x-www-form-urlencoded, multipart/form-data, or text/plain.
  • Does not set custom headers with the HTTP Request (such as X-Modified, etc.)

As you can read in bold, you must set other Content-Type for your data (currently it is contentType: "application/json; charset=utf-8",) or use the preflight technique described later:

  • It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
  • It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)

So I suggest you either change the contentType or try to work with this header into your request:

Access-Control-Request-Headers: X-HEADER_NAME_OF_YOUR_CHOOSE

and this headers into your response:

Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-HEADER_NAME_OF_YOUR_CHOOSE

And after that you can try to call your method.


Following is the solution for cross platform spring boot web service call.

Application URL: http://localhost:8080

Webservice URL: http://localhost:9090

In your spring controller use following annotation

@CrossOrigin(origins = "http://localhost:8080")
@RequestMapping(value = "/uri", method = RequestMethod.GET)
public SomeObject someMethod(){
// your logic will come here
}