2009-07-08 86 views
308

有什么我认为是一个相对简单的jQuery插件无法发送“OPTIONS”作为REQUEST_METHOD ...

插件应通过获取从PHP脚本数据ajax将选项添加到<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日志请求类型“选项”:

::1 - - [08/Jul/2009:11:43:27 -0500] "OPTIONS sitecodes.php HTTP/1.1" 200 46 

为什么会在Safari这Ajax调用的工作,而不是Firefox和我怎么修复它为Firefox?

 
Response Headers 
Date: Wed, 08 Jul 2009 21:22:17 GMT 
Server:Apache/2.0.59 (Unix) PHP/5.2.6 DAV/2 
X-Powered-By: PHP/5.2.6 
Content-Length 46 
Keep-Alive timeout=15, max=100 
Connection Keep-Alive 
Content-Type text/html 

Request Headers 
Host orderform:8888 
User-Agent Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1) Gecko/20090624 Firefox/3.5 
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 300 
Connection keep-alive 
Origin http://ux.inetu.act.org 
Access-Control-Request-Method POST 
Access-Control-Request-Headers x-requested-with 

这里是萤火虫输出的图片:

+0

你可以发布萤火虫响应和请求标题。当我在Firefox中运行类似的代码时,我没有收到任何错误。 – MitMaro 2009-07-08 18:37:58

+0

添加标题信息和Firebug的图片。 – fitzgeraldsteele 2009-07-08 21:37:56

+0

在实现嵌入式Web服务器时,只是遇到了同样的问题。感谢您提问:) – 2009-09-29 06:59:58

回答

161

的原因错误是同源策略。它只允许你为自己的域执行XMLHTTPRequests。看看你能不能用一个JSONP回调,而不是:

$.getJSON('http://<url>/api.php?callback=?', function (data) { alert (data); }); 
+0

注意:有关使用JSONP的信息,请参阅http://docs.jquery.com/Release:jQuery_1.2/Ajax#Cross-Domain_getJSON_.28using_JSONP.29。你需要额外的“=?”在你的查询字符串中触发JSONP – phirschybar 2009-11-04 16:31:15

+23

为什么firefox是唯一的浏览器呢?我想要一个帖子不是搞定的。 – Maslow 2010-04-01 16:17:03

+0

$ .getScript应该可以跨域,请参阅http://docs.jquery.com/Release:jQuery_1.2/Ajax#Cross-Domain_getScript(但它不适用于FF 3.6中的我) – blueyed 2010-05-14 16:15:10

2

我看来,如果o.url = 'index.php'且该文件存在是确定并在控制台返回成功消息。 http://www.google.com

如果做一个POST请求,为什么不直接使用的$.post方法:

$.post("test.php", { func: "getNameAndTime" }, 
    function(data){ 
     alert(data.name); // John 
     console.log(data.time); // 2pm 
    }, "json"); 

它是如此简单得多,如果我使用的URL,它返回一个错误。

+0

得到了与此相同的东西...以为我应该使用$ .ajax(),所以我至少可以得到一些调试信息的错误条件。 – fitzgeraldsteele 2009-07-08 21:38:33

0

你可以试试这个没有

contentType:application/x-www-form-urlencoded

+0

同样的结果,我害怕。 – fitzgeraldsteele 2009-07-09 13:12:17

0

尝试添加选项:

数据类型: “JSON”

4

我一直在寻找通过源1.3.2,使用JSONP时,请求是通过动态构建SCRIPT元素来完成的,该元素通过浏览器的相同域策略。当然,您不能使用SCRIPT元素发出POST请求,浏览器将使用GET获取结果。

当您请求JSONP调用时,不会生成SCRIPT元素,因为它仅在AJAX调用类型设置为GET时才执行此操作。

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

16

mozilla developer center article此描述了多种跨域请求场景。该文章似乎表明,应用程序发送的内容类型为'application/x-www-form-urlencoded'的POST请求应作为“简单请求”(不包含“预检”OPTIONS请求)发送。不过,我发现Firefox发送了OPTIONS请求,即使我的POST是使用该内容类型发送的。

我能够通过在服务器上创建一个选项请求处理程序来完成这项工作,该处理程序将'Access-Control-Allow-Origin'响应标头设置为'*'。通过将其设置为特定的内容,可以使其更具限制性,如'http://someurl.com'。此外,我读过,据推测,你可以指定多个来源的逗号分隔列表,但我无法让这个工作。

一旦火狐接收到选项的响应与可接受的“访问控制允许来源”值请求时,它发送POST请求。

0

我有一个类似的问题,试图使用Facebook API。

唯一的contentType其中没有发送预检请求似乎只是text/plain的...不是Mozilla的here

  • 上述参数的其余为什么这是做到这一点的唯一浏览器?
  • 为什么Facebook不知道并接受预检请求?

仅供参考:前面提到的Moz文件建议X-Lori头文件应该触发Preflighted请求......它没有。

1

解决此问题的另一种可能性是使用代理脚本。该方法被描述为example here

54

我用Django的侧下面的代码来解释该OPTIONS请求,并设定所要求的访问控制报头。在此之后,我的Firefox的跨域请求开始工作。正如前面所说的,浏览器首先会在选项后面的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。

2

检查您的表单的action网址是否包含域名的www部分,而您打开的原始网页是否在没有www的情况下查看。

为规范的URL通常做..

我挣扎了几个小时这篇文章后绊脚石之前,发现跨域的提示。

10

该响应脚本顶部的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); 
} 
1

解决方案是:

  1. 使用数据类型:json
  2. 添加&callback=?到您的网址

这工作在调用Facebook API和Firefox。 Firebug使用GET而不是OPTIONS以上述条件(两者都有)。

15

我已经使用完全基于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的执行你的目标脚本会发生什么。后者的积分为friendly ServerFault folk

7

我有同样的问题,将请求发送到谷歌地图,而解决办法是使用jQuery 1.5很简单 - 为的dataType使用dataType: "jsonp"

3

我们有一个问题,像这样与ASP.Net。我们的IIS在返回内部服务器错误时试图执行jQuery $.post以获取一些html内容,因为PageHandlerFactory被限制为仅响应GET,HEAD,POST,DEBUG动词。因此,您可以更改该限制,将动词“OPTIONS”添加到列表中或选择“所有动词”

您可以在IIS管理器中修改该选项,选择您的网站,然后选择Handler Mappings,双击PageHandlerFactory中的* .apx文件(我们在框架4.0中使用集成的应用程序池)。点击请求限制,然后转到动词Tabn并应用您的修改。现在

我们$.post要求按预期工作:)

0
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); 

    } 
});   
} 
0

你需要做服务器端的一些工作。我看你在服务器端使用PHP,但.NET Web应用程序的解决方案如下: Cannot set content-type to 'application/json' in jQuery.ajax

在PHP脚本中执行相同的操作,它将起作用。简单地说:首先请求浏览器询问服务器是否允许使用此类型发送此类数据,并且第二个请求是正确的/允许的。

0

尝试添加以下内容:

dataType: "json", 
ContentType: "application/json", 
data: JSON.stringify({"method":"getStates", "program":"EXPLORE"}), 
0

我使用代理网址时,我想将数据发布到另一个服务器托管我的Apache Solr实现解决类似的问题。 (这可能不是完美的答案,但它解决了我的问题。)

关注这个网址:Using Mode-Rewrite for proxying,我此行添加到我的httpd.conf:

RewriteRule ^solr/(.*)$ http://ip:8983/solr$1 [P] 

因此,我可以发布数据/ solr而不是将数据发布到http://ip:8983/solr/ *。然后它将发布相同来源的数据。

-1

请注意:

JSONP仅支持GET请求方法。

*由火狐发送请求:*

$.ajax({ 
    type: 'POST',//<<=== 
    contentType: 'application/json', 
    url: url, 
    dataType: "json"//<<============= 
    ... 
}); 

以上请求由OPTIONS发送(而==>类型: 'POST')!!!!

$.ajax({ 
    type: 'POST',//<<=== 
    contentType: 'application/json', 
    url: url, 
    dataType: "jsonp"//<<============== 
    ... 
}); 

但是上述请求通过发送GET(而==>类型: 'POST')!!!!

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

3

罪魁祸首是使用OPTIONS方法

对于HTTP请求的方法,可以导致在用户数据的副作用预检要求(特别地,用于HTTP方法比GET其他,或用于与某些MIME类型POST使用),该规范要求浏览器“预检”请求,使用HTTP OPTIONS请求方法从服务器请求支持的方法,然后在从服务器“批准”时,使用实际的HTTP请求方法发送实际请求。

网络规范是指:https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

我在Nginx的的c​​onf加入以下行解决了这个问题。

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; 
       } 
    } 
0

我已经有这个代码在PHP处理好我的CORS情况:

header('Access-Control-Allow-Origin: '.CMSConfig::ALLOW_DOMAIN); 
header('Access-Control-Allow-Headers: '.CMSConfig::ALLOW_DOMAIN); 
header('Access-Control-Allow-Credentials: true'); 

,这是工作的罚款本地和远程,但不适用于上传时,遥控器。

发生了一些事情与Apache/PHP或我的代码,我没有打扰搜索它,当你请求OPTIONS它返回我的标题与Cors规则但302结果。因此,我的浏览器不承认可接受的情况。

我做什么,基于@马克麦当劳的回答,只是把这个代码我的头之后:

if($_SERVER['REQUEST_METHOD'] === 'OPTIONS') 
{ 
    header("HTTP/1.1 202 Accepted"); 
    exit; 
} 

现在,请求OPTIONS时,它只会发送头和202的结果。