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时才会执行此操作。

http://dev.jquery.com/ticket/4690

我们有这样的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请求?

对此的解决方案是:

  1. 使用dataType: json
  2. 添加&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' )发送!!!!

当你在“跨域通信”时,要注意并小心。