Jquery – Ajax cross-domain request to REST api

ajaxcross-domainhttp-status-code-404jqueryrest

I have REST api on backend. I need to make ajax request to POST some data and I write:

$(function() { 
    $('#createPin').click(function(e) { 
        e.preventDefault();

var urlAjax = "http://www.agroagro.com/test/v1/register";

$.ajax({
type: "POST",
url: urlAjax,
contentType: "application/x-www-form-urlencoded",
data: {
                    name: "Mile3",
                    email: "new1@new.com",
                    password: "face1book"
                },
  crossDomain:true, 
  success: function(data) { console.log(data); },
error: function(data) {console.log(data); },
dataType: 'json',
beforeSend: function (xhr) {
            xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
        },
        headers: {
            'Access-Control-Allow-Origin': '*'
        }
});


}); 
});

but on click I get:

         OPTIONS http://www.agroagro.com/test/v1/register jquery-latest.min.js:4 sendjquery-latest.min.js:4 m.extend.ajaxtest.html:114 (anonymous function)jquery-latest.min.js:3 m.event.dispatchjquery-latest.min.js:3 r.handle

    XMLHttpRequest cannot load http://www.agroagro.com/test/v1/register. Invalid HTTP status code 404

    Object {readyState: 0, getResponseHeader: function, getAllResponseHeaders: function, 

setRequestHeader: function, overrideMimeType: function…}

But when I try to run http://www.agroagro.com/test/v1/register on Chrome Advanced Rest Client extension then all works fine… How and why? What is wrong with my ajax request?

See IMAGE: http://i.imgur.com/Ms0oBK9.pngas you can see all works great with that extension cross domain.

Best Solution

It is your backend API that needs to return the proper CORS header. In the easiest variant, just have the server reply to the preflight request (HTTP OPTIONS verb) with this header:

Access-Control-Allow-Origin: *

When you already have this response header set up, please note that your question shows a 404 code (Not Found). When I browse to http://www.agroagro.com/test/v1/register, I am seeing a 404, too. This may only be the case for GET requests, though.

By setting the crossDomain property to true, you are telling jQuery to send a JSONP request. A JSONP request works by embedding a <script> tag into the body, which triggers a GET request.

When the server is equipped with the proper CORS headers, you should disable crossDomain. Since, according to the jQuery documentation, crossDomain defaults to true if the target domain differs from the domain of the currently open web page, use this snippet:

$.ajax({ type: "POST", crossDomain: false, // ... });


For cross-domain requests, the browser sends a preflight request like this first:

OPTIONS /test/v1/register HTTP/1.1
Host: www.agroagro.com
Connection: keep-alive
Access-Control-Request-Method: POST
Origin: http://agroagro.com
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.62 Safari/537.36
Access-Control-Request-Headers: access-control-allow-origin, accept, x-requested-with, content-type
Accept: */*
Referer: http://agroagro.com/test.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4

To find out if the browser may send the POST request, the server response is checked for an Access-Control-Allow-Origin header. However, when receiving the above request, the API server replies like this:

HTTP/1.1 200 OK
Date: Fri, 28 Nov 2014 10:37:18 GMT
Content-Type: text/plain
Content-Length: 0
Connection: keep-alive
Set-Cookie: __cfduid=d57edcdbd0a20a0d11df4dda7c3753d611417171038; expires=Sat, 28-Nov-15 10:37:18 GMT; path=/; domain=.agroagro.com; HttpOnly
Allow: POST,OPTIONS,GET,HEAD
Set-Cookie: PH_HPXY_CHECK=s1; path=/
Cache-control: private
Server: cloudflare-nginx
CF-RAY: 1905edebcdb50f69-FRA

As you can see, there is no Access-Control-Allow-Origin header returned for the OPTIONS request.

Solution: Have the API endpoint return the Access-Control-Allow-Origin header not only for the POST request, but rather for the preflight OPTIONS request.