Search code examples
javascriptajaxsafari

CORS request working with Safari?


I understand why the following snippet doesn't work in Firefox and in Chrome: we're making an AJAX request to another domain.

var xhr = new XMLHttpRequest();
xhr.open("GET", "http://www.perdu.com", true);
xhr.addEventListener("load", function() { console.debug(xhr.responseText); }, false);
xhr.send(null);

But then why does Safari output this? This is the actual content of the page. I have Safari 7.1.

<html><head><title>Vous Etes Perdu ?</title></head><body><h1>Perdu sur l'Internet ?</h1><h2>Pas de panique, on va vous aider</h2><strong><pre>    * <----- vous &ecirc;tes ici</pre></strong></body></html>

Solution

  • Update

    It turns out that Safari behaves differently when loading from a server or from a file system.

    The original answer below tests the CORS functionality with a file:/// scheme. Safari lets users bypass CORS on that scheme.

    As Jonathan Crowe pointed out on localhost, so with the http:// scheme, Safari blocks the response, same as Firefox and Chrome.

    So there is no bug on this one. As for the behaviour on the file system, I guess we can call it a feature, or a convenience (thinking about quick local tests)?

    Note: This update relies on an additional, simple test to serve the HTML snippet below from an HTTP server. Nothing fancy, and Safari just behaves as the others.

    Original answer

    I could reproduce the problem. It might be a bug in Safari 7.1, and here is what I found toward that temporary conclusion.

    • Not reproducible on Safari 7.0.1 (see comment by Jonathan Crowe).
    • Two main differences:
      • Safari is the only browser that does NOT set the Origin header. Others set it to null.
      • The WebKit versions differ in Safari and Chrome.
    • No bug report related to CORS on Apple's tracking system.

    Also, this version of Safari allows setting the Origin header on the XMLHttpRequest object (Chrome does not):

    xhr.setRequestHeader("Origin", null);
    

    Setting the header to null to get closer to the other browsers does not change the result: Safari 7.1 still allows the response to get through to the requester.

    I could not make sure this is a bug in Safari 7.1, but it seems to be its behaviour right now.

    Some details below.

    Test page and code

    <html>
      <script>
        var xhr = new XMLHttpRequest();
        xhr.open("GET", "http://www.perdu.com", true);
        xhr.addEventListener("load", function() { console.debug(xhr.responseText); }, false);
        xhr.send(null);
      </script>
    </html>
    

    Tested versions

    • Safari 7.1 (9537.85.10.17.1)
    • Firefox 33.1
    • Chrome 38.0.2125.122

    (All on Mac OS X 10.9.5)

    Firefox request dump

    GET / HTTP/1.1
    Host: www.perdu.com
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:33.0) Gecko/20100101 Firefox/33.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Origin: null
    Connection: keep-alive
    

    Chrome request dump

    GET / HTTP/1.1
    Host: www.perdu.com
    Connection: keep-alive
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 Safari/537.36
    Origin: null
    Accept: */*
    DNT: 1
    Accept-Encoding: gzip,deflate,sdch
    Accept-Language: en-US,en;q=0.8,fr;q=0.6,ja;q=0.4,pt;q=0.2
    

    Safari request dump

    GET / HTTP/1.1
    Host: www.perdu.com
    Accept-Encoding: gzip, deflate
    Accept: */*
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10
    Accept-Language: en-us
    DNT: 1
    Connection: keep-alive
    

    Note

    I am currently testing edge cases with CORS over a range of browsers for a web API. If a bug gets confirmed, it shouldn't be too much of a problem---provided the API security is serious enough (as CORS does not secure the server) !

    Update

    I have asked Apple if they can confirm on their feedback site.