Как получить общий доступ к ресурсам кросс-происхождения (CORS) post запрос работает
у меня есть машина в моей локальной сети (machineA), которая имеет два веб-сервера. Первый-встроенный в XBMC (на порту 8080) и отображает нашу библиотеку. Второй сервер-это скрипт cherrypy python (порт 8081), который я использую для запуска преобразования файлов по требованию. Преобразование файлов инициируется запросом AJAX POST со страницы, обслуживаемой с сервера XBMC.
- перейти http://machineA:8080, который отображает библиотека
- библиотека отображается
- пользователь нажимает на ссылку "конвертировать", которая выдает следующую команду -
jQuery Ajax Request
$.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 ОК)
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:*)
для устранения неполадок, я также издал тот же $.сообщение команды отhttp://jquery.com. Вот где я в тупике, от jquery.com, почтовый запрос работает, запрос опций отправляется после поста. Заголовки из этого транзакция ниже;
заголовок запроса-параметры
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
заголовок запроса-сообщение
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 ОК)
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, который не делает вызовы на основе браузера и может обрабатывать перекрестные запросы происхождения.
например, Facebook JavaScript API и Google JS API.
в случае, если ваш поставщик API не является текущим и не поддерживает заголовок Cross Origin Resource Origin '*' в своем ответе и не имеет JS api (да I речь идет о вас, Yahoo ),вы поражены одним из трех вариантов-
используя jsonp в ваших запросах, который добавляет функцию обратного вызова к вашему URL, где вы можете обрабатывать свой ответ. Будьте осторожны, это изменит URL-адрес запроса, поэтому ваш сервер API должен быть оборудован для обработки ?обратный вызов= в конце URL-адреса.
отправить запрос на ваш сервер API, который является контроллером вами и находится либо в том же домене, что и клиент, либо имеет крест Общий доступ к ресурсам источника включен, откуда вы можете прокси-запрос на сторонний сервер API.
вероятно, наиболее полезно в тех случаях, когда вы делаете запросы OAuth и должны обрабатывать взаимодействие с пользователем ха-ха!
window.open('url',"newwindowname",'_blank', 'toolbar=0,location=0,menubar=0')
используя это в сочетании с Laravel решил мою проблему. Просто добавьте этот заголовок в свой запрос jquery
Access-Control-Request-Headers: x-requested-withи убедитесь, что ваш ответ на стороне сервера имеет этот заголовок setAccess-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 вызов:
<!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>вот 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>
Comments