2009-07-08 26 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的結果。