首先,說明一下案例性質,web調用restApi。
其次,說明一下案例的基本情況。我在本地編寫的web程式,後端程式儲存在遠端伺服器端,如166.66.66.6:8000/setup。
本次介紹的跨域的解決辦法,不涉及jsonp方式。而是需要将後端的代碼中設定Access-Control-Alow-Origin = “*”,表示允許一切跨域通路。Access-Control-Alow-Origin一次隻能設定一個域名,但是如果想要同時設定多個域名的話,解決辦法是,建立一個允許跨域請求的域名清單,然後擷取請求來源域名,和清單進行對比,如果來源域名存在允許的跨域請求域名清單裡面,再添加Access-Control-Alow-Origin響應頭。
第 一次出現問題的情況: $.ajax中設定url:“……”,data:{ “name”, “xiaobai”;“age”,“22” },type:“post”,則會發生報錯400,response提示{"ret":-1,"info":"Failed to parse JSON invalid character 'a' looking for beginning of value"},意思是傳送的資料沒能成功轉為JSON字元串。這時,将設定改為data:JSON.stringify{ “name”, “xiaobai”;“age”,“22” },dataType:“json”則成功。。這裡dataType是對傳回的資料進行格式的轉換。原了解釋一下,
注意,這裡出現的問題,如果web代碼和後端代碼在同一個域時,則會自動轉為JSON格式。而不需要JSON.stringify轉化。還有一點,若web代碼在本地,後端代碼在伺服器端,可以通過nginx代理,使其避開跨域問題的發生。
第二次出現問題的情況:如果隻是簡單的post發送方式,将json格式的資料發送到後端,則按照上述第一次出現的情況,即可解決問題。當需要在ajax中加入
beforeSend:function(xhr){
xhr.setRequestHeader("Authorization", userToken);
//xhr.setRequestHeader("Content-Type", "application/json");
},
時,又會出現報錯提示: Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response. 這 個時候,問題出現在content-type出現了問題。因為我們準備的資料時string格式的,同時ajax預設送出時告訴伺服器資料格式是 "'application/x-www-form-urlencoded",當我們用JSON.stringify轉化資料後,伺服器調用相關的 Converter解析的時候發現解析不了(因為我們的數 據格式其實是json格式)。由于content-type的不正确,導緻post方法,用options方式發送過去了。故而,由于發送方式不同,後端 不能正确接收資料。 解決辦法是(背景的處理方式):
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 ~ ^/(join|login|logout|user)$ {
if ($request_method = OPTIONS) {
rewrite ^(.*)$ / last;
}
}
第三次出現問題的情況,如果用angularjs的$http發送資料,則又會提示跨域的錯誤提示,那麼添加headers:{“content-type”:“ application/x-www-form-urlencoded ”};則請求成功。
綜上,雖然問題已經解決了,而且基本确定是content-type變化導緻的問題,可是我有幾點疑問沒有解決。
第一點,post變options是因為content-type的原因,可是我本地沒有設定request的content-type,後端沒有設定response的content-type,而是隻在後端設定了if ($request_method = OPTIONS) {rewrite ^(.*)$ / last;},就能解決跨域問題。這是為什麼?
第二點是,JSON.stringify使content-type預設值改變,導緻問題發生,可以隻在背景設定了Access-Control-Allow-Headers=“*”,而沒有設定request的content-type就成功了,這又是為什麼?
以上均為個人了解,有誤之處,請指正。也希望有大神幫忙解決一下我的問題~~~
http://www.cnblogs.com/taoys/archive/2010/12/30/1922186.html 講解content-type中application/x-www-form-urlencoded内容;
http://fyq891014.blog.163.com/blog/static/20074019120123305029795/ 講解jquery,ajax參數的問題;
http://www.cnblogs.com/yeer/archive/2009/07/23/1529460.html 講解jquery中ajax參數問題(更詳細);
首先,說明一下案例性質,web調用restApi。
其次,說明一下案例的基本情況。我在本地編寫的web程式,後端程式儲存在遠端伺服器端,如166.66.66.6:8000/setup。
本次介紹的跨域的解決辦法,不涉及jsonp方式。而是需要将後端的代碼中設定Access-Control-Alow-Origin = “*”,表示允許一切跨域通路。Access-Control-Alow-Origin一次隻能設定一個域名,但是如果想要同時設定多個域名的話,解決辦法是,建立一個允許跨域請求的域名清單,然後擷取請求來源域名,和清單進行對比,如果來源域名存在允許的跨域請求域名清單裡面,再添加Access-Control-Alow-Origin響應頭。
第 一次出現問題的情況: $.ajax中設定url:“……”,data:{ “name”, “xiaobai”;“age”,“22” },type:“post”,則會發生報錯400,response提示{"ret":-1,"info":"Failed to parse JSON invalid character 'a' looking for beginning of value"},意思是傳送的資料沒能成功轉為JSON字元串。這時,将設定改為data:JSON.stringify{ “name”, “xiaobai”;“age”,“22” },dataType:“json”則成功。。這裡dataType是對傳回的資料進行格式的轉換。原了解釋一下,
注意,這裡出現的問題,如果web代碼和後端代碼在同一個域時,則會自動轉為JSON格式。而不需要JSON.stringify轉化。還有一點,若web代碼在本地,後端代碼在伺服器端,可以通過nginx代理,使其避開跨域問題的發生。
第二次出現問題的情況:如果隻是簡單的post發送方式,将json格式的資料發送到後端,則按照上述第一次出現的情況,即可解決問題。當需要在ajax中加入
beforeSend:function(xhr){
xhr.setRequestHeader("Authorization", userToken);
//xhr.setRequestHeader("Content-Type", "application/json");
},
時,又會出現報錯提示: Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response. 這 個時候,問題出現在content-type出現了問題。因為我們準備的資料時string格式的,同時ajax預設送出時告訴伺服器資料格式是 "'application/x-www-form-urlencoded",當我們用JSON.stringify轉化資料後,伺服器調用相關的 Converter解析的時候發現解析不了(因為我們的數 據格式其實是json格式)。由于content-type的不正确,導緻post方法,用options方式發送過去了。故而,由于發送方式不同,後端 不能正确接收資料。 解決辦法是(背景的處理方式):
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 ~ ^/(join|login|logout|user)$ {
if ($request_method = OPTIONS) {
rewrite ^(.*)$ / last;
}
}
第三次出現問題的情況,如果用angularjs的$http發送資料,則又會提示跨域的錯誤提示,那麼添加headers:{“content-type”:“ application/x-www-form-urlencoded ”};則請求成功。
綜上,雖然問題已經解決了,而且基本确定是content-type變化導緻的問題,可是我有幾點疑問沒有解決。
第一點,post變options是因為content-type的原因,可是我本地沒有設定request的content-type,後端沒有設定response的content-type,而是隻在後端設定了if ($request_method = OPTIONS) {rewrite ^(.*)$ / last;},就能解決跨域問題。這是為什麼?
第二點是,JSON.stringify使content-type預設值改變,導緻問題發生,可以隻在背景設定了Access-Control-Allow-Headers=“*”,而沒有設定request的content-type就成功了,這又是為什麼?
不确定,我寫的這些是否正确,如果疑問,歡迎指正。也希望有大神幫忙解決一下我的問題~
http://www.cnblogs.com/taoys/archive/2010/12/30/1922186.html 講解content-type中application/x-www-form-urlencoded内容;
http://fyq891014.blog.163.com/blog/static/20074019120123305029795/ 講解jquery,ajax參數的問題;
http://www.cnblogs.com/yeer/archive/2009/07/23/1529460.html 講解jquery中ajax參數問題(更詳細);