falta la cabecera cors ''access-control-allow-origin'' jquery
Cómo obtener una solicitud de publicación de uso compartido de recursos de origen cruzado(CORS) (9)
Tengo una máquina en mi LAN local (machineA) que tiene dos servidores web. El primero es el integrado en XBMC (en el puerto 8080) y muestra nuestra biblioteca. El segundo servidor es un script python CherryPy (puerto 8081) que estoy usando para activar una conversión de archivos a pedido. La conversión de archivos se desencadena mediante una solicitud AJAX POST desde la página servida desde el servidor XBMC.
- Vaya a http: // machineA: 8080 que muestra la biblioteca
- Biblioteca se muestra
- El usuario hace clic en el enlace ''convertir'' que emite el siguiente comando:
Solicitud jQuery Ajax
$.post(''http://machineA:8081'', {file_url: ''asfd''}, function(d){console.log(d)})
- El navegador emite una solicitud HTTP OPTIONS con los siguientes encabezados;
Encabezado de solicitud - OPCIONES
Host: machineA:8081
User-Agent: ... Firefox/4.01
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
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://machineA:8080
Access-Control-Request-Method: POST
Access-Control-Request-Headers: x-requested-with
- El servidor responde con lo siguiente;
Encabezado de respuesta - OPCIONES (ESTADO = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:40:29 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
- La conversación se detiene. El navegador, en teoría, debe emitir una solicitud POST ya que el servidor respondió con los encabezados CORS correctos (?) (Access-Control-Allow-Origin: *)
Para la resolución de problemas, también he emitido el mismo comando $ .post desde http://jquery.com . Aquí es donde estoy perplejo, desde jquery.com, la solicitud de publicación funciona, una solicitud de OPCIONES se envía después de un POST. Los encabezados de esta transacción están debajo;
Encabezado de solicitud - OPCIONES
Host: machineA:8081
User-Agent: ... Firefox/4.01
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
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Origin: http://jquery.com
Access-Control-Request-Method: POST
Encabezado de respuesta - OPCIONES (ESTADO = 200 OK)
Content-Length: 0
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: text/html;charset=ISO-8859-1
Encabezado de solicitud: POST
Host: machineA:8081
User-Agent: ... Firefox/4.01
Accept: */*
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://jquery.com/
Content-Length: 12
Origin: http://jquery.com
Pragma: no-cache
Cache-Control: no-cache
Encabezado de respuesta - POST (ESTADO = 200 OK)
Content-Length: 32
Access-Control-Allow-Headers: *
Access-Control-Max-Age: 1728000
Server: CherryPy/3.2.0
Date: Thu, 21 Apr 2011 22:37:59 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: POST, GET, OPTIONS
Content-Type: application/json
No puedo entender por qué la misma solicitud funcionaría desde un sitio, pero no desde el otro. Espero que alguien pueda señalar lo que me estoy perdiendo. ¡Gracias por tu ayuda!
Bueno, tuve problemas con este tema durante un par de semanas.
La manera más fácil, más compatible y no hacky de hacer esto es probablemente usar una API de JavaScript de proveedor que no haga llamadas basadas en navegador y pueda manejar solicitudes Cross Origin.
Por ejemplo, Facebook JavaScript API y Google JS API.
En caso de que su proveedor de API no esté actualizado y no soporte el encabezado Cross Origin Resource Origin ''*'' en su respuesta y no tenga una api de JS (sí, estoy hablando de ti, Yahoo), te sorprenderá una de las tres opciones:
Usando jsonp en sus solicitudes, que agrega una función de devolución de llamada a su URL donde puede manejar su respuesta. Tenga en cuenta que esto cambiará la URL de solicitud para que su servidor API esté equipado para gestionar la devolución de llamada = al final de la URL.
Envíe la solicitud a su servidor API, que es su controlador y está en el mismo dominio que el cliente o tiene Cross Origin Resource Sharing habilitado desde donde puede proxy la solicitud al servidor API de terceros.
Probablemente sea más útil en los casos en los que realiza solicitudes de OAuth y necesita manejar la interacción del usuario ¡Jaja!
window.open(''url'',"newwindowname",''_blank'', ''toolbar=0,location=0,menubar=0'')
Este es un resumen de lo que funcionó para mí:
Defina una nueva función (envuelto $.ajax
para simplificar):
jQuery.postCORS = function(url, data, func) { if(func == undefined) func = function(){}; return $.ajax({ type: ''POST'', url: url, data: data, dataType: ''json'', contentType: ''application/x-www-form-urlencoded'', xhrFields: { withCredentials: true }, success: function(res) { func(res) }, error: function() { func({}) }}); }
Uso:
$.postCORS("https://example.com/service.json",{ x : 1 },function(obj){
if(obj.ok) {
...
}
});
También funciona con .done
, .fail
, etc.
$.postCORS("https://example.com/service.json",{ x : 1 }).done(function(obj){
if(obj.ok) {
...
}
}).fail(function(){
alert("Error!");
});
En el lado del servidor (en este caso, donde está alojado example.com), configure estos encabezados (se agregó un código de muestra en PHP):
header(''Access-Control-Allow-Origin: https://not-example.com'');
header(''Access-Control-Allow-Credentials: true'');
header(''Access-Control-Max-Age: 604800'');
header("Content-type: application/json");
$array = array("ok" => $_POST["x"]);
echo json_encode($array);
Esta es la única forma que conozco de POSTAR dominios cruzados de JS.
JSONP convierte la POST en GET que puede mostrar información confidencial en los registros del servidor.
Esto es un poco tarde para la fiesta, pero he estado luchando con esto por un par de días. Es posible y ninguna de las respuestas que encontré aquí ha funcionado. Es engañosamente simple. Aquí está la llamada .ajax:
<!DOCTYPE HTML>
<html>
<head>
<body>
<title>Javascript Test</title>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
$(document).domain = ''XXX.com'';
$(document).ready(function () {
$.ajax({
xhrFields: {cors: false},
type: "GET",
url: "http://XXXX.com/test.php?email=''[email protected]''",
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert(x.responseText + " :EEE: " + x.status);
}
});
});
</script>
</body>
</html>
Aquí está el php en el lado del servidor:
<html>
<head>
<title>PHP Test</title>
</head>
<body>
<?php
header(''Origin: xxx.com'');
header(''Access-Control-Allow-Origin:*'');
$servername = "sqlxxx";
$username = "xxxx";
$password = "sss";
$conn = new mysqli($servername, $username, $password);
if ($conn->connect_error) {
die( "Connection failed: " . $conn->connect_error);
}
$sql = "SELECT email, status, userdata FROM msi.usersLive";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
echo $row["email"] . ":" . $row["status"] . ":" . $row["userdata"] . "<br>";
}
} else {
echo "{ }";
}
$conn->close();
?>
</body>
Finalmente me topé con este enlace " Una solicitud CORS POST funciona desde JavaScript simple, pero ¿por qué no con jQuery? " Que señala que jQuery 1.5.1 agrega el
Access-Control-Request-Headers: x-requested-with
encabezado a todas las solicitudes CORS. jQuery 1.5.2 no hace esto. Además, de acuerdo con la misma pregunta, establecer un encabezado de respuesta del servidor de
Access-Control-Allow-Headers: *
no permite que la respuesta continúe. Debe asegurarse de que el encabezado de respuesta incluya específicamente los encabezados necesarios. es decir:
Access-Control-Allow-Headers: x-requested-with
Me llevó algo de tiempo encontrar la solución.
En caso de que la respuesta del servidor sea correcta y la solicitud sea el problema, debe agregar withCredentials: true
a xhrFields
en la solicitud:
$.ajax({
url: url,
type: method,
// This is the important part
xhrFields: {
withCredentials: true
},
// This is the important part
data: data,
success: function (response) {
// handle the response
},
error: function (xhr, status) {
// handle errors
}
});
Nota: se requiere jQuery> = 1.5.1
Por alguna razón, una pregunta sobre las solicitudes GET se fusionó con esta, por lo que responderé aquí.
Esta sencilla función obtendrá asíncronamente una respuesta de estado HTTP desde una página habilitada para CORS. Si lo ejecuta, verá que solo una página con los encabezados adecuados devuelve un estado de 200 si se accede a través de XMLHttpRequest, ya sea que se use GET o POST. No se puede hacer nada en el lado del cliente para evitar esto, excepto posiblemente usando JSONP si solo necesita un objeto json.
Lo siguiente se puede modificar fácilmente para obtener los datos contenidos en el objeto xmlHttpRequestObject:
function checkCorsSource(source) {
var xmlHttpRequestObject;
if (window.XMLHttpRequest) {
xmlHttpRequestObject = new XMLHttpRequest();
if (xmlHttpRequestObject != null) {
var sUrl = "";
if (source == "google") {
var sUrl = "https://www.google.com";
} else {
var sUrl = "https://httpbin.org/get";
}
document.getElementById("txt1").innerHTML = "Request Sent...";
xmlHttpRequestObject.open("GET", sUrl, true);
xmlHttpRequestObject.onreadystatechange = function() {
if (xmlHttpRequestObject.readyState == 4 && xmlHttpRequestObject.status == 200) {
document.getElementById("txt1").innerHTML = "200 Response received!";
} else {
document.getElementById("txt1").innerHTML = "200 Response failed!";
}
}
xmlHttpRequestObject.send();
} else {
window.alert("Error creating XmlHttpRequest object. Client is not CORS enabled");
}
}
}
<html>
<head>
<title>Check if page is cors</title>
</head>
<body>
<p>A CORS-enabled source has one of the following HTTP headers:</p>
<ul>
<li>Access-Control-Allow-Headers: *</li>
<li>Access-Control-Allow-Headers: x-requested-with</li>
</ul>
<p>Click a button to see if the page allows CORS</p>
<form name="form1" action="" method="get">
<input type="button" name="btn1" value="Check Google Page" onClick="checkCorsSource(''google'')">
<input type="button" name="btn1" value="Check Cors Page" onClick="checkCorsSource(''cors'')">
</form>
<p id="txt1" />
</body>
</html>
Resolví mi propio problema al usar la API de matriz de distancia de google configurando el encabezado de mi solicitud con Jquery ajax. mira abajo
var settings = {
''cache'': false,
''dataType'': "jsonp",
"async": true,
"crossDomain": true,
"url": "https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=place_id:"+me.originPlaceId+"&destinations=place_id:"+me.destinationPlaceId+"®ion=ng&units=metric&key=mykey",
"method": "GET",
"headers": {
"accept": "application/json",
"Access-Control-Allow-Origin":"*"
}
}
$.ajax(settings).done(function (response) {
console.log(response);
});
Tenga en cuenta lo que agregué en la configuración
**
"headers": {
"accept": "application/json",
"Access-Control-Allow-Origin":"*"
}
**
Espero que esto ayude.
SOLICITUD:
$.ajax({
url: "http://localhost:8079/students/add/",
type: "POST",
crossDomain: true,
data: JSON.stringify(somejson),
dataType: "json",
success: function (response) {
var resp = JSON.parse(response)
alert(resp.status);
},
error: function (xhr, status) {
alert("error");
}
});
RESPUESTA:
response = HttpResponse(json.dumps(''{"status" : "success"}''))
response.__setitem__("Content-type", "application/json")
response.__setitem__("Access-Control-Allow-Origin", "*")
return response
Usar esto en combinación con Laravel resolvió mi problema. Simplemente agregue este encabezado a su solicitud de jquery: Access-Control-Request-Headers: x-requested-with
y asegúrese de que su respuesta del lado del servidor tenga este encabezado configurado como Access-Control-Allow-Headers: *
.