2011-06-18 40 views
30

Estoy justando la función $.getJSON() de jQuery para devolver un conjunto corto de datos JSON.jQuery.getJSON - Access-Control-Allow-Origin Problema

Tengo los datos JSON en una url como example.com. No me di cuenta, pero como estaba accediendo a la misma URL, no se pudieron cargar los datos JSON. Seguí a través de la consola y encontré que XMLHttpRequest no se pudo cargar debido a Access-Control-Allow-Origin.

Ahora, he leído, muchos sitios que acabo de decir que usan $.getJSON() y que sería el trabajo correcto, pero obviamente no funcionó. ¿Hay algo que deba cambiar en los encabezados o en la función?

La ayuda es muy apreciada.

+2

Quizás le interese consultar JSONP: http://en.wikipedia.org/wiki/JSONP. – pimvdb

+0

Una alternativa sería reenviar su solicitud y respuesta utilizando un proxy (por ejemplo, PHP curl) si eso está disponible para usted. – Dan

Respuesta

36

Es posible que desee utilizar JSON-P en su lugar (ver a continuación). Primero una explicación rápida.

El encabezado que ha mencionado es del estándar Cross Origin Resource Sharing. Tenga en cuenta que es not supported por algunos navegadores que las personas realmente usan, y en otros navegadores (Microsoft, suspiro) requiere usar un objeto especial (XDomainRequest) en lugar del estándar XMLHttpRequest que usa jQuery. También requiere que cambie los recursos del lado del servidor para permitir explícitamente el otro origen (www.xxxx.com).

para obtener los datos JSON que está solicitando, usted tiene básicamente tres opciones:

  1. Si es posible, puede ser compatible con el máximo mediante la corrección de la ubicación de los archivos que se va a cargar por lo que tienen el mismo origen que el documento en el que los está cargando. (Supongo que debe cargarlos a través de Ajax, de ahí que aparezca el problema Same Origin Policy)

  2. Use JSON-P, que no está sujeto al SOP. jQuery tiene soporte integrado en su llamada ajax (simplemente configure dataType en "jsonp" y jQuery hará todo el trabajo del lado del cliente). Esto requiere cambios en el servidor, pero no muy grandes; básicamente, cualquier cosa que tenga que genere la respuesta JSON solo busca un parámetro de cadena de consulta llamado "devolución de llamada" y ajusta el JSON en código JavaScript que llamaría a esa función. Por ejemplo, si su respuesta JSON actual es:

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

    Su guión se vería para el parámetro de cadena de consulta "callback" (digamos que el valor del parámetro es "jsop123") y envuelve que JSON en la sintaxis de una JavaScript llamada de función:

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

    Eso es todo. JSON-P es muy ampliamente compatible (porque funciona a través de las etiquetas JavaScript script). JSON-P es solo para GET, sin embargo, no POST (una vez más porque funciona a través de las etiquetas script).

  3. Utilice CORS (el mecanismo relacionado con el encabezado que citó). Detalles en the specification linked above, pero básicamente:

    A. El navegador enviará a su servidor un mensaje "Preflight" utilizando el OPTIONS verbo HTTP (método).Contendrá los distintos encabezados que enviaría con GET o POST, así como los encabezados "Origen", "Método de solicitud de control de acceso" (p. Ej., GET o POST) y "Cabeceras de solicitud de control de acceso". (los encabezados que quiere enviar).

    B. Su PHP decide, basándose en esa información, si la solicitud es correcta y si responde con "Access-Control-Allow-Origin", "Access-Control-Allow-Methods" y "Access- Encabezados Control-Allow-Headers "con los valores que permitirá. No envía ningún cuerpo (página) con esa respuesta.

    C. El navegador examinará su respuesta y verá si se le permite enviar el GET o POST. Si es así, enviará esa solicitud, nuevamente con el "Origen" y varios encabezados "Access-Control-Request-xyz".

    D. Su PHP examina esos encabezados nuevamente para asegurarse de que siguen estando bien, y en caso afirmativo responde a la solicitud.

    En seudo -code (no he hecho mucho de PHP, así que no estoy tratando de hacer aquí sintaxis de 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 
    

    De nuevo haciendo hincapié en que se trata de pseudo-código.

+0

¿Hay alguna manera de hacer esto utilizando jQuery? O bien, ¿hay un encabezado que pueda establecer (a través de PHP) que permita que esto funcione? – Mike

+0

@Mike: ¿Qué "esto"? Si se refiere a JSON-P, sí, jQuery lo admite en su llamada 'ajax'; He agregado algunos detalles arriba. Si se refiere a CORS, entonces sí, son los encabezados que establece a través de PHP en respuesta a una solicitud HTTP 'OPTIONS' y de nuevo en respuesta a' GET' o 'POST'; He agregado algunos detalles para eso también. Pero es demasiado exagerado si hay alguna posibilidad de que solo muevas los archivos para que estén en el mismo origen. –

+0

@ T.J.Crowder So $ .getJSON no funciona? ¿Necesitamos usar algún otro método como ajax y configurar los encabezados? – Dinesh

66

Es muy sencillo, utilizar $.getJSON() función y en su URL basta con incluir

devolución de llamada =?

como parámetro. Eso convertirá la llamada a JSONP que es necesaria para realizar llamadas entre dominios. Más información: http://api.jquery.com/jQuery.getJSON/

+18

Eso depende por completo de el servidor acepta el parámetro de devolución de llamada adicional que no puede hacer en todos los casos. – Simon

+7

Esto no funciona el 100% del tiempo, como si el servidor no estuviera configurado para el servidor jsonp, entonces aún devuelve json, en el cual se producirá un error. – chadpeppers

+1

¡Eso funciona para mí, gracias! – FrontENG