jQuery.getJSON - Access-Control-Allow-Origin Issue

112,476

Solution 1

It's simple, use $.getJSON() function and in your URL just include

callback=?

as a parameter. That will convert the call to JSONP which is necessary to make cross-domain calls. More info: http://api.jquery.com/jQuery.getJSON/

Solution 2

You may well want to use JSON-P instead (see below). First a quick explanation.

The header you've mentioned is from the Cross Origin Resource Sharing standard. Beware that it is not supported by some browsers people actually use, and on other browsers (Microsoft's, sigh) it requires using a special object (XDomainRequest) rather than the standard XMLHttpRequest that jQuery uses. It also requires that you change server-side resources to explicitly allow the other origin (www.xxxx.com).

To get the JSON data you're requesting, you basically have three options:

  1. If possible, you can be maximally-compatible by correcting the location of the files you're loading so they have the same origin as the document you're loading them into. (I assume you must be loading them via Ajax, hence the Same Origin Policy issue showing up.)

  2. Use JSON-P, which isn't subject to the SOP. jQuery has built-in support for it in its ajax call (just set dataType to "jsonp" and jQuery will do all the client-side work). This requires server side changes, but not very big ones; basically whatever you have that's generating the JSON response just looks for a query string parameter called "callback" and wraps the JSON in JavaScript code that would call that function. E.g., if your current JSON response is:

    {"weather": "Dreary start but soon brightening into a fine summer day."}
    

    Your script would look for the "callback" query string parameter (let's say that the parameter's value is "jsop123") and wraps that JSON in the syntax for a JavaScript function call:

    jsonp123({"weather": "Dreary start but soon brightening into a fine summer day."});
    

    That's it. JSON-P is very broadly compatible (because it works via JavaScript script tags). JSON-P is only for GET, though, not POST (again because it works via script tags).

  3. Use CORS (the mechanism related to the header you quoted). Details in the specification linked above, but basically:

    A. The browser will send your server a "preflight" message using the OPTIONS HTTP verb (method). It will contain the various headers it would send with the GET or POST as well as the headers "Origin", "Access-Control-Request-Method" (e.g., GET or POST), and "Access-Control-Request-Headers" (the headers it wants to send).

    B. Your PHP decides, based on that information, whether the request is okay and if so responds with the "Access-Control-Allow-Origin", "Access-Control-Allow-Methods", and "Access-Control-Allow-Headers" headers with the values it will allow. You don't send any body (page) with that response.

    C. The browser will look at your response and see whether it's allowed to send you the actual GET or POST. If so, it will send that request, again with the "Origin" and various "Access-Control-Request-xyz" headers.

    D. Your PHP examines those headers again to make sure they're still okay, and if so responds to the request.

    In pseudo-code (I haven't done much PHP, so I'm not trying to do PHP syntax here):

    // Find out what the request is asking for
    corsOrigin = get_request_header("Origin")
    corsMethod = get_request_header("Access-Control-Request-Method")
    corsHeaders = get_request_header("Access-Control-Request-Headers")
    if corsOrigin is null or "null" {
        // Requests from a `file://` path seem to come through without an
        // origin or with "null" (literally) as the origin.
        // In my case, for testing, I wanted to allow those and so I output
        // "*", but you may want to go another way.
        corsOrigin = "*"
    }
    
    // Decide whether to accept that request with those headers
    // If so:
    
    // Respond with headers saying what's allowed (here we're just echoing what they
    // asked for, except we may be using "*" [all] instead of the actual origin for
    // the "Access-Control-Allow-Origin" one)
    set_response_header("Access-Control-Allow-Origin", corsOrigin)
    set_response_header("Access-Control-Allow-Methods", corsMethod)
    set_response_header("Access-Control-Allow-Headers", corsHeaders)
    if the HTTP request method is "OPTIONS" {
        // Done, no body in response to OPTIONS
        stop
    }
    // Process the GET or POST here; output the body of the response
    

    Again stressing that this is pseudo-code.

Share:
112,476
Admin
Author by

Admin

Updated on June 03, 2020

Comments

  • Admin
    Admin about 4 years

    I'm jusing jQuery's $.getJSON() function to return a short set of JSON data.

    I've got the JSON data sitting on a url such as example.com. I didn't realize it, but as I was accessing that same url, the JSON data couldn't be loaded. I followed through the console and found that XMLHttpRequest couldn't load due to Access-Control-Allow-Origin.

    Now, I've read through, a lot of sites that just said to use $.getJSON() and that would be the work around, but obviously it didn't work. Is there something I should change in the headers or in the function?

    Help is greatly appreciated.

  • Admin
    Admin about 13 years
    Is there a way to do this utilizing jQuery? Or, is there a header I can set (via PHP) that will let this work?
  • T.J. Crowder
    T.J. Crowder about 13 years
    @Mike: Which "this"? If you mean JSON-P, yes, jQuery supports that in its ajax call; I've added some details above. If you mean CORS, then yes, that's headers you set via PHP in response to an OPTIONS HTTP request and again in response to the GET or POST; I've added some details for that as well. But it's all overkill if there's any chance you can just move the files so they're on the same origin.
  • Simon
    Simon almost 12 years
    That depends entirely on the server accepting the extra callback parameter which it may not do in all cases.
  • chadpeppers
    chadpeppers over 10 years
    This doesn't work 100% of the time as if the server is not set up to server jsonp then it still returns json, in which you will get an error.
  • Dinesh
    Dinesh about 10 years
    @T.J.Crowder So $.getJSON does not work? do we need to use some other method like ajax and set the headers?
  • T.J. Crowder
    T.J. Crowder about 10 years
    @Dinesh: $.getJSON works fine provided either 1) It's a same-origin request, or 2) The browser and server both support CORS and the server allows the origin, or 3) The server provides a JSON-P interface and you tell jQuery you're using JSON-P by using ?callback= in the URL you give $.getJSON.
  • Dinesh
    Dinesh about 10 years
    @T.J.Crowder Ok.. Could you please answer this question - stackoverflow.com/questions/22795561/…
  • smartmouse
    smartmouse about 4 years
    In my case I have CORS issue sometimes, not every time I open the site. So now I have applied this workaround but I cannot see if I have solved.
  • Nevada Stone
    Nevada Stone about 3 years