Как получить общий доступ к ресурсам кросс-происхождения (CORS) post request working
у меня есть машина на моей локальной сети (machineA), которая имеет два веб-сервера. Первый-встроенный в XBMC (на порту 8080) и отображает нашу библиотеку. Второй сервер-это скрипт cherrypy python (порт 8081), который я использую для запуска преобразования файлов по требованию. Преобразование файлов инициируется запросом AJAX POST со страницы, обслуживаемой сервером XBMC.
- перейти http://machineA:8080, который отображает библиотека
- библиотека отображается
- пользователь нажимает на ссылку "конвертировать", которая выдает следующую команду -
jQuery Ajax запрос
$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})
- браузер выдает запрос параметров HTTP со следующими заголовками;
заголовок запроса-параметры
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
- сервер отвечает следующим образом;
заголовок ответа-параметры (статус = 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
- затем разговор прекращается. Браузер, теоретически, должен выдать запрос POST, поскольку сервер ответил правильным (?) Заголовки CORS (Access-Control-Allow-Origin: *)
для устранения неполадок, я также издал тот же $.команда post от http://jquery.com. Вот откуда я в тупике. jquery.com, запрос post работает, запрос опций отправляется после POST. Заголовки из этого транзакции ниже;
заголовок запроса-параметры
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
заголовок ответа-параметры (статус = 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
заголовок запроса-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
заголовок ответа-сообщение (статус = 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
Я не могу понять, почему один и тот же запрос будет работать с одного сайта, а не другой. Я надеюсь, что кто-то сможет указать, кто я недостающий. Спасибо за помощь!
10 ответов
я, наконец, наткнулся на эту ссылку "запрос CORS POST работает с простого javascript, но почему бы не с jQuery?", которое отмечает, что jQuery 1.5.1 добавляет
Access-Control-Request-Headers: x-requested-with
заголовок для всех запросов CORS. jQuery 1.5.2 этого не делает. Кроме того, в соответствии с тем же вопросом, установка заголовка ответа сервера
Access-Control-Allow-Headers: *
не позволяет продолжить ответ. Вы должны убедиться, что заголовок ответа специально включает необходимые заголовки. то есть:
Access-Control-Allow-Headers: x-requested-with
запрос:
$.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");
}
});
ответ:
response = HttpResponse(json.dumps('{"status" : "success"}'))
response.__setitem__("Content-type", "application/json")
response.__setitem__("Access-Control-Allow-Origin", "*")
return response
мне потребовалось некоторое время, чтобы найти решение.
В случае, если ваш ответ сервера правильно и запрос проблему, вы должны добавить withCredentials: true
до xhrFields
запрос:
$.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
}
});
Примечание: jQuery > = 1.5.1 is требуются
Ну, я боролся с этой проблемой за пару недель.
самый простой, наиболее совместимый и не хакерский способ сделать это, вероятно, использовать провайдер JavaScript API, который не делает браузерных вызовов и может обрабатывать запросы Cross Origin.
например. Facebook JavaScript API и Google JS API.
в случае, если ваш поставщик API не является текущим и не поддерживает заголовок Cross Origin Resource Origin '*' в своем ответе и не имеет api JS (да I речь идет о вас, Yahoo ),вы поражены одним из трех вариантов-
используя jsonp в ваших запросах, который добавляет функцию обратного вызова к вашему URL, где вы можете обрабатывать свой ответ. Будьте осторожны, это изменит URL-адрес запроса, поэтому ваш сервер API должен быть оборудован для обработки ?callback= в конце URL-адреса.
отправьте запрос на ваш сервер API, который является контроллером вами и находится в том же домене, что и клиент, или имеет Кросс Общий доступ к ресурсам источника включен, откуда вы можете прокси-запрос на сторонний сервер API.
вероятно, наиболее полезно в случаях, когда вы делаете запросы OAuth и должны обрабатывать взаимодействие с пользователем ха-ха!
window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')
используя это в сочетании с Laravel решил мою проблему. Просто добавьте этот заголовок в свой запрос jQuery Access-Control-Request-Headers: x-requested-with
и убедитесь, что ваш ответ на стороне сервера имеет этот набор заголовков Access-Control-Allow-Headers: *
.
Я решил свою проблему при использовании Google distance matrix API, установив заголовок запроса с помощью jQuery ajax. посмотрите ниже.
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);
});
обратите внимание, что я добавил в параметры
**
"headers": {
"accept": "application/json",
"Access-Control-Allow-Origin":"*"
}
**
Надеюсь, это поможет.
по какой-то причине вопрос о запросах GET был объединен с этим, поэтому я отвечу на него здесь.
эта простая функция асинхронно получит ответ состояния HTTP со страницы с поддержкой CORS. Если вы запустите его, вы увидите, что только страница с соответствующими заголовками возвращает статус 200 при доступе через XMLHttpRequest -- используется ли GET или POST. Ничего нельзя сделать на стороне клиента, чтобы обойти это, за исключением, возможно, использования JSONP, если вам просто нужен json объект.
для получения данных, хранящихся в объекте 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>
У меня была точно такая же проблема, когда jQuery ajax только дал мне проблемы cors на post-запросах, где get-запросы работали нормально - я устал все выше без результатов. У меня были правильные заголовки на моем сервере и т. д. Переход на использование XMLHTTPRequest вместо jquery немедленно исправил мою проблему. Независимо от того, какую версию jquery я использовал, это не исправило. Выборки также работает без проблем, если вам не нужна обратная совместимость браузера.
var xhr = new XMLHttpRequest()
xhr.open('POST', 'https://mywebsite.com', true)
xhr.withCredentials = true
xhr.onreadystatechange = function() {
if (xhr.readyState === 2) {// do something}
}
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(json)
надеюсь, это поможет кому-нибудь еще с теми же проблемами.
это резюме того, что сработало для меня:
определите новую функцию (wrapped $.ajax
для упрощения):
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({})
}
});
}
использование:
$.postCORS("https://example.com/service.json",{ x : 1 },function(obj){
if(obj.ok) {
...
}
});
работает с .done
,.fail
, etc:
$.postCORS("https://example.com/service.json",{ x : 1 }).done(function(obj){
if(obj.ok) {
...
}
}).fail(function(){
alert("Error!");
});
сторона сервера (в этом случае, где example.com размещен), установите эти заголовки (добавлен пример кода в 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);
это единственный способ, который я знаю, чтобы действительно опубликовать кросс-домен из JS.
JSONP преобразует сообщение в GET который может отображать конфиденциальную информацию в журналах сервера.
это немного поздно для вечеринки, но я боролся с этим в течение нескольких дней. Возможно, и ни один из ответов я нашел здесь работали. Это обманчиво просто. Вот это .ajax call:
<!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='steve@XXX.com'",
success: function (data) {
alert(data);
},
error: function (x, y, z) {
alert(x.responseText + " :EEE: " + x.status);
}
});
});
</script>
</body>
</html>
вот php на стороне сервера:
<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>