jQuery.getJSON - Access-Control-Allow-Origin Issue - PullRequest
36 голосов
/ 18 июня 2011

Я использую функцию jQuery $.getJSON() для возврата короткого набора данных JSON.

У меня есть данные JSON, расположенные по URL-адресу, например example.com. Я не осознавал этого, но когда я обращался к тому же URL-адресу, данные JSON не могли быть загружены. Я проследовал через консоль и обнаружил, что XMLHttpRequest не может загрузиться из-за Access-Control-Allow-Origin.

Теперь, я прочитал, много сайтов, которые только что сказали использовать $.getJSON(), и это будет обходной путь, но, очевидно, это не сработало. Что-то, что я должен изменить в заголовках или в функции?

Помощь очень ценится.

Ответы [ 2 ]

73 голосов
/ 03 июня 2012

Это просто, используйте функцию $.getJSON() и в свой URL просто включите

Обратный вызов =?

в качестве параметра. Это преобразует вызов в JSONP, который необходим для выполнения междоменных вызовов. Дополнительная информация: http://api.jquery.com/jQuery.getJSON/

38 голосов
/ 18 июня 2011

Возможно, вы захотите использовать вместо этого JSON-P (см. Ниже).Сначала краткое объяснение.

Упомянутый вами заголовок взят из стандарта Cross Origin Resource Sharing .Имейте в виду, что не поддерживается некоторыми браузерами, которые фактически используются людьми, а в других браузерах (Microsoft, sigh ) требуется использование специального объекта (XDomainRequest), а не стандартного XMLHttpRequest, который использует jQuery.Также требуется, чтобы вы изменили ресурсы на стороне сервера, чтобы явно разрешить другое происхождение (www.xxxx.com).

Чтобы получить запрашиваемые данные JSON, у вас в основном есть три варианта:

  1. Если возможно, вы можете быть максимально совместимыми, исправляя расположение загружаемых файлов, чтобы они имели то же происхождение, что и документ, в который вы их загружаете.(Я предполагаю, что вы должны загружать их через Ajax, поэтому появляется проблема Same Origin Policy .)

  2. Use JSON-P ,который не подпадает под СОП.jQuery имеет встроенную поддержку для него в своем вызове ajax (просто установите dataType в значение "jsonp", и jQuery выполнит всю работу на стороне клиента).Это требует изменений на стороне сервера, но не очень больших;в основном все, что у вас есть, генерирующее ответ JSON, просто ищет параметр строки запроса под названием «обратный вызов» и оборачивает JSON в код JavaScript, который будет вызывать эту функцию.Например, если ваш текущий ответ JSON:

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

    Ваш сценарий будет искать параметр строки запроса "обратный вызов" (скажем, что значением параметра является "jsop123") и заключает этот JSON в синтаксис длявызов функции JavaScript:

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

    Вот и все.JSON-P очень широко совместим (потому что он работает через теги JavaScript script).JSON-P предназначен только для GET, но не POST (опять же, потому что он работает через script теги).

  3. Используйте CORS (механизм, связанный с заголовком, который выцитируем).Подробности в спецификации, связанной выше , но в основном:

    A.Браузер отправит вашему серверу сообщение «preflight», используя HTTP-глагол OPTIONS (метод).Он будет содержать различные заголовки, которые он будет отправлять с GET или POST, а также заголовки "Origin", "Access-Control-Request-Method" (например, GET или POST) и "Access-Control-Request-Headers "(заголовки, которые он хочет отправить).

    B.Ваш PHP на основе этой информации решает, в порядке ли запрос и, если да, отвечает «Access-Control-Allow-Origin», «Access-Control-Allow-Methods» и «Access-Control-Allow-Headers»Заголовки со значениями, которые это позволит.Вы не отправляете тела (страницы) с таким ответом.

    C.Браузер проверит ваш ответ и выяснит, разрешено ли вам отправлять действительные значения GET или POST.Если это так, он отправит этот запрос снова с заголовками «Origin» и различными заголовками «Access-Control-Request-xyz».

    D.Ваш PHP проверяет эти заголовки снова , чтобы убедиться, что они все еще в порядке, и, если это так, отвечает на запрос.

    В псевдо -код (у меня нетсделал много PHP, поэтому я не пытаюсь делать здесь синтаксис PHP):

    // 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
    

    Еще раз подчеркивая, что это псевдокод.

...