jQuery $ .ajax(),$ .post在Firefox中发送“OPTIONS”作为REQUEST_METHOD
遇到麻烦,我认为是一个相对简单的jQuery插件…
该插件应该通过ajax从php脚本中获取数据,以便将选项添加到<select>
。 ajax请求非常通用:
$.ajax({ url: o.url, type: 'post', contentType: "application/x-www-form-urlencoded", data: '{"method":"getStates", "program":"EXPLORE"}', success: function (data, status) { console.log("Success!!"); console.log(data); console.log(status); }, error: function (xhr, desc, err) { console.log(xhr); console.log("Desc: " + desc + "\nErr:" + err); } });
这似乎在Safari中正常工作。 在Firefox 3.5中,服务器上的REQUEST_TYPE
始终为“OPTIONS”,$ _POST数据不会显示。 Apache将请求记录为“OPTIONS”类型:
::1 - - [08/Jul/2009:11:43:27 -0500] "OPTIONS sitecodes.php HTTP/1.1" 200 46
为什么这个AJAX调用工作在Safari,但不是Firefox,我该如何解决它的Firefox?
响应头 日期:2009年七月8日(星期三)21:22:17 GMT 服务器:Apache / 2.0.59(Unix)PHP / 5.2.6 DAV / 2 X-Powered-By:PHP / 5.2.6 内容长度46 保持活动超时= 15,最大= 100 连接保持活动 内容类型文本/ HTML 请求头 主机订单:8888 用户代理Mozilla / 5.0(Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1)Gecko / 20090624 Firefox / 3.5 接受text / html,application / xhtml + xml,application / xml; q = 0.9,* / *; q = 0.8 Accept-Language en-us,en; q = 0.5 接受编码gzip,放气 Accept-Charset ISO-8859-1,utf-8; q = 0.7,*; q = 0.7 保持活力300 连接保持活着 起源http://ux.inetu.act.org 访问控制请求方法POST 访问控制请求报头x请求
这里是Firebug输出的图片:
错误的原因是相同的原产地政策。 它只允许你对自己的域做XMLHTTPRequests。 看看你是否可以使用JSONP回调:
$.getJSON( 'http://<url>/api.php?callback=?', function ( data ) { alert ( data ); } );
我在Django端使用了下面的代码来解释OPTIONS请求并设置所需的访问控制标题。 在这之后,我从Firefox的跨域请求开始工作。 如前所述,浏览器首先发送OPTIONS请求,然后立即发送POST / GET
def send_data(request): if request.method == "OPTIONS": response = HttpResponse() response['Access-Control-Allow-Origin'] = '*' response['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS' response['Access-Control-Max-Age'] = 1000 # note that '*' is not valid for Access-Control-Allow-Headers response['Access-Control-Allow-Headers'] = 'origin, x-csrftoken, content-type, accept' return response if request.method == "POST": # ...
编辑:它似乎是,至少在某些情况下,您还需要添加相同的访问控制标头实际的响应。 这可能有点混乱,因为请求似乎成功了,但是Firefox并没有将响应的内容传递给Javascript。
这个mozilla开发者中心文章描述了各种跨域请求场景。 文章似乎表明,应用程序发送一个内容类型为“application / x-www-form-urlencoded”的POST请求作为“简单请求”(没有“预检”选项请求)。 然而,我发现Firefox发送了OPTIONS请求,即使我的POST是使用该内容类型发送的。
我可以通过在服务器上创建一个选项请求处理程序来完成这项工作,即将“Access-Control-Allow-Origin”响应标头设置为“*”。 您可以通过将其设置为特定的内容来进行更多的限制,比如“ http://someurl.com ”。 此外,我已经读过,据说,你可以指定一个逗号分隔的多个来源列表,但我无法得到这个工作。
一旦Firefox收到对OPTIONS请求的响应,并且具有可接受的“Access-Control-Allow-Origin”值,它就会发送POST请求。
我已经使用完全基于Apache的解决方案解决了此问题。 在我的虚拟主机/ htaccess我把以下块:
# enable cross domain access control Header always set Access-Control-Allow-Origin "*" Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS" # force apache to return 200 without executing my scripts RewriteEngine On RewriteCond %{REQUEST_METHOD} OPTIONS RewriteRule .* / [R=200,L]
您可能不需要后者,这取决于Apache执行目标脚本时发生的情况。 信用交给后期友好的ServerFault人 。
响应脚本顶部的这个PHP似乎工作。 (使用Firefox 3.6.11,我还没有做很多测试。)
header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: POST, GET, OPTIONS'); header('Access-Control-Max-Age: 1000'); if(array_key_exists('HTTP_ACCESS_CONTROL_REQUEST_HEADERS', $_SERVER)) { header('Access-Control-Allow-Headers: ' . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']); } else { header('Access-Control-Allow-Headers: *'); } if("OPTIONS" == $_SERVER['REQUEST_METHOD']) { exit(0); }
我有同样的问题发送请求到谷歌地图,解决方案是相当简单的jQuery 1.5 – dataType使用dataType: "jsonp"
我正在通过源代码1.3.2来查看,当使用JSONP时,请求是通过动态构建SCRIPT元素来完成的,该代码将通过浏览器的相同域策略。 当然,您不能使用SCRIPT元素发出POST请求,浏览器将使用GET获取结果。
在请求JSONP调用时,不会生成SCRIPT元素,因为只有在AJAX调用类型设置为GET时才会执行此操作。
我们有这样的ASP.Net的问题。 我们的IIS在尝试执行jQuery $.post
来获取一些html内容时返回了内部服务器错误,因为PageHandlerFactory被限制为仅响应GET,HEAD,POST,DEBUG
动词。 所以你可以改变这个限制,把动词“OPTIONS”添加到列表中或者选择“All Verbs”
您可以在IIS管理器中修改该选项,选择您的网站,然后选择处理程序映射,双击您的PageHandlerFactory中的* .apx文件(我们使用带有框架4.0的集成应用程序池)。 点击请求限制,然后转到动词Tabn并应用您的修改。
现在我们的$.post
请求正在按预期工作:)
检查您的表单的action
网址是否包含网域的www
部分,而您打开的原始网页是否在没有www
情况下查看。
通常为Canonical Urls完成
在挣扎了这篇文章之前,我挣扎了好几个小时,发现了Cross Domain的暗示。
我似乎如果o.url = 'index.php'
,这个文件存在是好的,并在控制台中返回一个成功的消息。 如果我使用url: http://www.google.com
: http://www.google.com
它会返回错误
如果做一个post请求,为什么不直接使用$ .post方法:
$.post("test.php", { func: "getNameAndTime" }, function(data){ alert(data.name); // John console.log(data.time); // 2pm }, "json");
它是如此简单。
罪魁祸首是使用OPTIONS方法的预检请求
对于可能对用户数据造成副作用的HTTP请求方法(特别是对于GET以外的HTTP方法,或者对于某些MIME类型的POST方法),规范要求浏览器“预检”请求,请求服务器与HTTP OPTIONS请求方法,然后,在从服务器“批准”,发送实际的请求与实际的HTTP请求方法。
Web规范参考: https : //developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
我通过在Nginx conf中添加以下行来解决了这个问题。
location / { if ($request_method = OPTIONS ) { add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "POST, GET, PUT, UPDATE, DELETE, OPTIONS"; add_header Access-Control-Allow-Headers "Authorization"; add_header Access-Control-Allow-Credentials "true"; add_header Content-Length 0; add_header Content-Type text/plain; return 200; } location ~ ^/(xxxx)$ { if ($request_method = OPTIONS) { rewrite ^(.*)$ / last; } }
我已经发布了一个清晰的例子,说明如何解决这个问题,如果控制你所在域的服务器代码。 这个答案在这个线程中被触及,但是这更清楚地解释了IMO。
如何通过JavaScript发送跨域POST请求?
对此的解决方案是:
- 使用dataType:
json
- 添加
&callback=?
到您的网址
这工作在调用Facebook API和Firefox。 Firebug使用GET
而不是OPTIONS
来满足上述条件(两者都是)。
绕过这个问题的另一种可能性是使用代理脚本。 这个方法在这里举例说明
你可以尝试没有
contentType:application/x-www-form-urlencoded
尝试添加选项:
dataType:“json”
function test_success(page,name,id,divname,str) { var dropdownIndex = document.getElementById(name).selectedIndex; var dropdownValue = document.getElementById(name)[dropdownIndex].value; var params='&'+id+'='+dropdownValue+'&'+str; //makerequest_sp(url, params, divid1); $.ajax({ url: page, type: "post", data: params, // callback handler that will be called on success success: function(response, textStatus, jqXHR){ // log a message to the console document.getElementById(divname).innerHTML = response; var retname = 'n_district'; var dropdownIndex = document.getElementById(retname).selectedIndex; var dropdownValue = document.getElementById(retname)[dropdownIndex].value; if(dropdownValue >0) { //alert(dropdownValue); document.getElementById('inputname').value = dropdownValue; } else { document.getElementById('inputname').value = "00"; } return; url2=page2; var params2 = parrams2+'&'; makerequest_sp(url2, params2, divid2); } }); }
我有一个类似的问题,试图使用Facebook的API。
唯一没有发送Preflighted请求的contentType似乎只是text / plain …而不是mozilla中提到的其他参数
- 为什么这是唯一的浏览器呢?
- 为什么Facebook不知道并接受预检请求?
仅供参考:前面提到的Moz文件建议X-Lori标题应该触发Preflighted请求…它不。
你需要在服务器端做一些工作。 我看到你在服务器端使用PHP,但.NET Web应用程序的解决方案是这样的: 无法在jQuery.ajax中将content-type设置为“application / json”
在PHP脚本中做同样的事情,它会工作。 简单地说:首先请求浏览器询问服务器是否被允许发送这种类型的数据,第二个请求是适当/允许的。
尝试添加以下内容:
dataType: "json", ContentType: "application/json", data: JSON.stringify({"method":"getStates", "program":"EXPLORE"}),
我用一个代理url来解决类似的问题,当我想发布数据到我的apache solr托管在另一台服务器。 (这可能不是完美的答案,但它解决了我的问题。)
按照这个URL: 使用Mode-Rewrite进行代理 ,我将这一行添加到我的httpd.conf中:
RewriteRule ^solr/(.*)$ http://ip:8983/solr$1 [P]
因此,我可以将数据发布到/ solr,而不是将数据发布到http:// ip:8983 / solr / *。 然后它将发布数据在同一个来源。
我已经有这个代码处理好我的Cors在PHP的情况:
header( 'Access-Control-Allow-Origin: '.CMSConfig::ALLOW_DOMAIN ); header( 'Access-Control-Allow-Headers: '.CMSConfig::ALLOW_DOMAIN ); header( 'Access-Control-Allow-Credentials: true' );
它在本地和远程工作正常,但不能在远程上传。
有些事情发生在Apache / PHP或我的代码,我没有打扰搜索它,当你请求选择它返回我的标题与Cors规则,但302结果。 因此,我的浏览器不认可为可接受的情况。
我所做的,基于@Mark麦克唐纳的答案,只是把这个代码放在我的头后面:
if( $_SERVER['REQUEST_METHOD'] === 'OPTIONS' ) { header("HTTP/1.1 202 Accepted"); exit; }
现在,当请求OPTIONS
它只会发送头和202结果。
请注意:
JSONP仅支持GET请求方法。
*发送请求由Firefox :*
$.ajax({ type: 'POST',//<<=== contentType: 'application/json', url: url, dataType: "json"//<<============= ... });
以上请求通过OPTIONS发送(while ==> type:'POST' )!!!!
$.ajax({ type: 'POST',//<<=== contentType: 'application/json', url: url, dataType: "jsonp"//<<============== ... });
但是上面的请求通过GET (while ==> type:'POST' )发送!!!!
当你在“跨域通信”时,要注意并小心。