Ajax cross-Omain request with pure Javascript (no Apis)

Asked

Viewed 35,092 times

27

I have two applications in different domains, and I need to make a request Ajax between them saw POST or GET so cross-Domain.

What would be the safest way to implement this in Javascript, without making use of any API or framework in a way that works in all browsers (cross-browser)?

  • Interesting article. It can clarify doubts on this same theme. http://blog.dtisistemas.com.br/sharing/

3 answers

28


The two main options are the CORS (cross-origin resource sharing) and the JSONP (JSON with padding). Both require some server support (in the form of request headers or supported response formats), but CORS does not need anything special on the client side (except a browser to support it - which is a fact in all modern browsers).

Cross-Origin Resource Sharing

As explained by @Tiago Crizanto, CORS consists of the send server header Access-Control-Allow-Origin next to the responses to the requests. There are some boring details (preflight, etc) but this in general is the very browser that takes care. All your Javascript code has to do is a normal Ajax request, as explained in your other question.

(Note: second this tutorial [in English], some versions of IE may need to be used XDomainRequest instead of the traditional XMLHttpRequest; I don’t have enough experience to give more details, so I suggest observing it if you need to support old browsers)

Examples:

  1. Enabling CORS on the server:

    Access-Control-Allow-Origin: *
    
  2. Enabling CORS on the server for specific domains only (i.e. only the domain example.com and example.net can send Ajax requests to it):

    Access-Control-Allow-Origin: http://example.com http://example.net
    
  3. Enabling the sending of cookies. By default, when making an Ajax request to another domain, cookies (for example, authentication) are not included. Putting this header will make this done (caring for: may have implications on the security of your website).

    Access-Control-Allow-Credentials: true
    

    and in Javascript:

    var req = createXMLHTTPObject();
    req.withCredentials = true;
    ...
    
  4. Exposing additional headers to Javascript code (by default, only headers Cache-Control, Content-Language, Content-Type, Expires, Last-Modified and Pragma are visible to the client code):

    Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
    

The advantage lies in the greater security: the data from the remote server is sent as the same data, noncode, so that you can give them the most appropriate treatment. The downside is that older browsers may not support it (according to the caniuse with., apart from the entire Opera Mini browser in its current version accepts it; IE8 and IE9 give partial support, and I believe that IE7 backwards does not support).

JSON with Padding

This technique in my opinion is more a "gambiarra" than a solution itself - but it is popular enough to be supported in major web frameworks (such as jQuery), and before CORS was one of the only ways to do this without resorting to external plugins or browser-specific features. It’s simple to implement, and works in any browser [that has Javascript], although it’s not exactly a "secure" solution (i.e. it should only be used if the site where the request is made is reliable).

JSONP takes advantage of the fact that some tags are exempt of same origin policy (Same-Origin Policy) - among them the script. Since JSON is a popular data transfer format, and it is a subset of Javascript object literals, one could transmit data of this type:

{"Name": "Foo", "Id" : 1234, "Rank": 7}

using this format:

minhaFuncao({"Name": "Foo", "Id" : 1234, "Rank": 7});

To do this, just create a tag script specifying which function you want to be called (the equivalent of callback ajax) and put the request in the attribute src. Example (in practice, use the format supported by your server):

var script = document.createElement('script');
script.src = 'http://example.com/jsonp?callback=minhaFuncao'; // + outros parâmetros
document.getElementsByTagName('head')[0].appendChild(script);

And on the server, just serialize your answer as JSON and then "wrap it" in the callback specified. Example (Django):

objeto = {"Name": "Foo", "Id" : 1234, "Rank": 7}
codificado_json = json.dumps(objeto)
callback = request.GET["callback"]                  # ex.: "minhaFuncao"
resposta = callback + "(" + codificado_json + ");"  #      "minhaFuncao({...})
return HttpResponse(resposta, mimetype="text/javascript")

The advantage is the greater compatibility with all types of browser (it would not even need to support Ajax). The downside is in the requirement to reliability: the value returned by the server is a common Javascript code, and it runs in the same context on the home page. This means that if the server sends malicious code instead of the expected JSONP, this code can simply do whatever you want on your page (but limited to what is accessible via Javascript, which is practically all, but excludes things like cookies HTTP-ONLY). That is, your website will be exposed to an XSS vulnerability (Cross-site scripting) - what may or may not be "manageable", but in general is a situation to be avoided whenever possible.

  • Thank you for the full reply ;)

  • And by the way, the part about Access-Control-Allow-Credentials helped me solve another problem!

5

Man... I had this problem a while back. The options I found were:

1 Setting iis to allow cross-Omain requests; (In my case I didn’t have this option, so I didn’t test)

2 Do the ajax request normally and modify the http header in c# (if you are using .NET. You can do a php too):

Response.AppendHeader("Access-Control-Allow-Origin", "*");

https://stackoverflow.com/questions/15534640/ajax-origin-localhost-is-not-allowed-by-access-control-allow-origin

3 I looked for a pure js solution but could not find it. The solution I found was using jquery (jsonp). No need to make any of the above changes.

$.ajax({
     type : "GET",
     dataType : "jsonp",
     url : "URL",
     success: function(data){

     }
});
  • What is the difference between your options 1 and 2? In other words, "setting iis to allow cross-Omain requests" is not the same thing as doing it [automatically] setting the header Access-Control-Allow-Origin? Or is it something else?

  • Changing the header by code (Response.Appendheader("Access-Control-Allow-Origin", "*");) is an option when you don’t have access to IIS settings.

  • jQuery is a third API...

  • 2

    @Gabrielgartz jQuery facilitates the use of JSONP, but it is not necessary for such. I am writing a reply with more details, soon I put here.

  • 1

    Just to remind you that JSONP only requests in GET, because it adds in DOM the SCRIPT tag, I think the ideal was someone find a story that talks about the subject to clarify these things to the boy of the question.

3

The usual solution to take a server resource dynamically without using Jquery or other API is to create the script tag and add in the head section of the page, where you point the src attribute to the URL of the resource you want to get.

This URL is from a Javascript script normally generated by the server with code that returns values or executes code to do the action you want. This is used to send requests using the GET method.

An alternative that serves to send requests by the POST method, including sending forms up uploading files, that of having a hidden iframe with a given name. There you have a form that you change the target attribute to the iframe name. So when the form is sent, the result loads in the iframe and the whole page is not reloaded.

In this iframe you can even return HTML with Javascript that executes code that does something useful to your page like return data, change messages on the page, etc..

These solutions work with GET and POST methods, can work in cross-Omain, do not require browser Suport AJAX 2 and requires no API. I once wrote an article about it to explain how to do upload files and show upload progress with PHP on the server side.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.