Как получить запрос на совместное использование ресурсов (CORS)
У меня есть машина на моем локальном компьютере (machineA) с двумя веб-серверами. Первый - встроенный в XBMC (порт 8080) и отображает нашу библиотеку. Второй сервер - это python CherryPy script (порт 8081), который я использую для запуска преобразования файлов по требованию. Преобразование файла инициируется запросом AJAX POST со страницы, обслуживаемой сервером XBMC.
- Перейти к http://machineA:8080, который отображает библиотеку
- Отображается библиотека
- Пользователь нажимает на ссылку "convert", которая выдает следующую команду:
Запрос jQuery Ajax
$.post('http://machineA:8081', {file_url: 'asfd'}, function(d){console.log(d)})
- Браузер выдает запрос HTTP OPTIONS со следующими заголовками:
Заголовок запроса - ОПЦИИ
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
- Сервер отвечает следующим образом:
Заголовок ответа - ОПЦИИ (STATUS = 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, работает почтовый запрос, запрос OPTIONS отправляется после 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
Заголовок ответа - ОПЦИИ (STATUS = 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
Заголовок ответа - POST (STATUS = 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
Я не могу понять, почему один и тот же запрос будет работать с одного сайта, но не с другим. Я надеюсь, что кто-то сможет указать, что мне не хватает. Спасибо за вашу помощь!
Ответы
Ответ 1
Я, наконец, наткнулся на эту ссылку Запрос 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
Ответ 2
ПРОСЬБА:
$.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
Ответ 3
Пришло время найти решение.
В случае, если ваш ответ сервера правильно и запрос является проблемой, вы должны добавить 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 требуется
Ответ 4
Хорошо, я боролся с этой проблемой в течение пары недель.
Самый простой, наиболее совместимый и не хакерский способ сделать это - это, вероятно, использовать JavaScript-провайдер провайдера, который не выполняет вызовы на основе браузера и может обрабатывать запросы Cross Origin.
например. API Facebook JavaScript и API Google JS.
В случае, если ваш поставщик API не является текущим и не поддерживает заголовок Origins Origins '*' в своем ответе и не имеет JS api (да, я говорю о вас Yahoo), вас поражает одна из трех параметры -
-
Использование jsonp в ваших запросах, которое добавляет функцию обратного вызова к вашему URL, где вы можете обрабатывать свой ответ.
Предостережение это изменит URL-адрес запроса, чтобы ваш сервер API был оборудован для обработки обратного вызова? В конце URL-адреса.
-
Отправьте запрос на ваш сервер API, который является вашим контроллером, и находится либо в том же домене, что и клиент, либо включен перекрестный источник ресурсов, откуда вы можете проксировать запрос на сторонний сервер API.
-
Вероятно, наиболее полезно в тех случаях, когда вы делаете запросы OAuth и должны обрабатывать взаимодействие с пользователем. Ха-ха! window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')
Ответ 5
Использование этого в сочетании с Laravel решило мою проблему. Просто добавьте этот заголовок в свой запрос jQuery Access-Control-Request-Headers: x-requested-with
и убедитесь, что ваш ответ на стороне сервера имеет этот набор заголовков Access-Control-Allow-Headers: *
.
Ответ 6
Я решил свою собственную проблему при использовании API-интерфейсов google distance, установив свой заголовок запроса с помощью 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":"*"
}
**
Надеюсь, это поможет.
Ответ 7
Это резюме того, что сработало для меня:
Определите новую функцию (упростите $.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
и т.д.
$.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);
Это единственный способ узнать правду POST кросс-домена от JS.
JSONP преобразует POST в GET, который может отображать конфиденциальную информацию в журналах сервера.
Ответ 8
По какой-то причине вопрос о запросах 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>
Ответ 9
У меня была одна и та же проблема, когда jquery ajax только дал мне проблемы с коревыми вопросами в почтовых запросах, где запросы выполнялись нормально - я устал от всего выше, без каких-либо результатов. У меня были правильные заголовки на моем сервере и т.д. Переключение на использование XMLHTTPRequest вместо jquery немедленно исправило мою проблему. Независимо от того, какую версию jquery я использовал, это не исправило. Fetch также работает без проблем, если вам не нужна совместимость с обратным браузером.
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)
Надеюсь, это поможет кому-то еще с теми же проблемами.
Ответ 10
Это немного поздно для вечеринки, но я боролся с этим пару дней. Это возможно, и ни один из ответов, которые я нашел здесь, не работал. Это обманчиво просто.
Здесь вызов .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>