Manish Kumar
Manish Kumar

Reputation: 10492

Spring REST api not working while hosted remotely

I have written a spring rest service. When i was running it on localhost it was running well

        $.ajax({
            url:"http://localhost:8080/api/v1.0/basicSignup",
            type:"POST",
            contentType:"application/json",

but when i tried & hosted on some remote server

        $.ajax({
            url:"http://X.X.X.X/api/v1.0/basicSignup",
            type:"POST",
            contentType:"application/json",

it throwing error

In chrome

XMLHttpRequest cannot load http://X.X.X.X/api/v1.0/basicSignup. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://localhost:8084' is therefore not allowed access.

In console i see that in Method tab it show options

In mozilla also it shows OPTIONS.

Response Headersview source
Allow   GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length  0
Date    Sat, 15 Aug 2015 15:15:07 GMT
Server  Apache-Coyote/1.1
Request Headersview source
Accept  text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding gzip, deflate
Accept-Language en-us,en;q=0.5
Access-Control-Request-He...    content-type
Access-Control-Request-Me...    POST
Cache-Control   no-cache
Connection  keep-alive
DNT 1
Host    X.X.X.X
Origin  null
Pragma  no-cache
User-Agent  Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:13.0) Gecko/20100101 Firefox/13.0.1

Upvotes: 0

Views: 912

Answers (1)

Sanjay
Sanjay

Reputation: 8955

As @JB's comment says, you might need to implement CORS. Basically, the single origin policy wouldn't allow JavaScript from one domain, say http://localhost:8084 to make AJAX calls to another domain, say http://X.X.X.X by default. There are some mechanisms for handling this, but people seem to prefer CORS, because generally it looks most convenient and powerful.

Spring Lemon exhibits how to use CORS in details. Below is an example from another project of mine:

  1. In the client code, I would set up these ajax options initially (or along with each call)

    $.ajaxSetup({    // Initialize options for AJAX calls
    
        crossDomain: true,
    
        xhrFields: {
            withCredentials: true
        }
        ...
    });
    
  2. At the server side, have a filter which will set the CORS headers. The latest version of Spring (which would come along with Spring Boot 1.3) has an easier way to configure CORS at the server side. But, in one project using Spring Boot 1.2, I would have it like this:

    @Component
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public class SimpleCorsFilter implements Filter {
    
        @Value("${applicationUrl:http://localhost:8084}")
        String applicationUrl;
    
        public void doFilter(ServletRequest req,
                ServletResponse res,
                FilterChain chain)
        throws IOException, ServletException {
    
            HttpServletResponse response = (HttpServletResponse) res;
            response.setHeader("Access-Control-Allow-Origin",
                applicationUrl); // "*" does not work when withCredentials = true;
            response.setHeader("Access-Control-Allow-Methods",
                "GET, POST, PUT, PATCH, DELETE, OPTIONS");
            response.setHeader("Access-Control-Max-Age",
                "3600");
            response.setHeader("Access-Control-Allow-Headers",
                "x-requested-with,origin,content-type,accept,X-XSRF-TOKEN");
            response.setHeader("Access-Control-Allow-Credentials", "true"); // needed when withCredentials = true;
    
            HttpServletRequest request =  (HttpServletRequest) req;
    
            if (!request.getMethod().equals("OPTIONS"))
               chain.doFilter(req, res);
        }
    
        public void init(FilterConfig filterConfig) {}
    
        public void destroy() {}
    }
    
  3. Set applicationUrl in application.properties, like this

    applicationUrl: http://X.X.X.X
    

Upvotes: 1

Related Questions