我們只想做一個安分的軟件“工程師”挤聘,只想專注于業(yè)務(wù)邏輯(因為老板只盯著他所關(guān)注的功能、版本衣盾、優(yōu)化)寺旺,不立志成為計算機“科學家”,解決那些底層的雨效、不兼容、各種奇葩的實現(xiàn)(因為老板不覺得自己應(yīng)該給這些“科研”工作出經(jīng)費)废赞。于是徽龟,從一開始,我們就本著“只要實現(xiàn)功能就行”的不科學態(tài)度唉地,在基礎(chǔ)知識上沒有系統(tǒng)學習過……直到幾次讓人非常沮喪据悔、非常被動的情況發(fā)生,我們才不得不審視一直以來的“短視”耘沼。
jsonp存在的問題
硬問題:
- 不支持POST方法
jsonp基于GET方法實現(xiàn)极颓,并沒有用XMLHttpRequest,不是真正的ajax請求群嗤。所以菠隆,僅有jsonp是不夠的,服務(wù)端無論如何都免不了支持CORS狂秘。 - 欲捕獲服務(wù)端返回的500等錯誤骇径,捕獲不到。jquery有文檔明確說明:(function error) This handler is not called for cross-domain script and cross-domain JSONP requests. 我還不甚了了why
軟問題:
服務(wù)端需要支持兩種方式者春,而這種機制性的代碼又不常改(除非出問題)破衔。平時前端、后端都專注業(yè)務(wù)邏輯钱烟,前端沒毛病晰筛,后端同學是萬萬不會想到這個代碼嫡丙。某一天,前端發(fā)現(xiàn)了問題读第,思量 “記得xx點原來是可以的啊曙博,怎么今天不行了……”,又是一番google卦方,一番嘗試羊瘩,結(jié)果發(fā)現(xiàn):哦,原來是jsonp可以盼砍,json不行(要么就是json可以尘吗,jsonp不行)。這就是記憶的局限浇坐。畢竟睬捶,看不到對方代碼,記憶中是支持的近刘,卻常常忽略了“兩種方式”這件事擒贸。
注意:下面說的都是棄用jsonp后遇到的問題
ajax帶不上cookie
這樣子做:
1) Add the following to your ajax request.
xhrFields: { withCredentials:true }
2) Add the following to your response headers for resources in the different subdomain.
Access-Control-Allow-Origin : http://original.mydomain.com
Access-Control-Allow-Credentials : true
The XMLHttpRequest.withCredentials property is a Boolean that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates. Setting withCredentials has no effect on same-site requests.
IE8/IE9不支持ajax
我一直以為XMLHttpRequest是瀏覽器的標配,事實告訴我觉渴,真是沒見過世面介劫!人家偉大的IE8/IE9就不標配,有自己的XDomainRequest
幸好案淋,有人為jquery寫了插件jQuery-ajaxTransport-XDomainRequest座韵。在引入jquery.js之后引入它,$.ajax的地方不用改踢京,齊活誉碴。
強調(diào)一下,如果你引入了插件瓣距,發(fā)現(xiàn)仍然是返回500錯誤黔帕,請確認返回頭中有Access-Control-Allow-Origin。
CORS requires the Access-Control-Allow-Origin header to be present in the AJAX response from the server.
我在這里費了好半天勁蹈丸。因在我的印象中成黄,我們一直是返回這個header的,否則在chrome逻杖、safari上早該有問題了慨默。所以,在我讀插件的文檔時看到這句話弧腥,很自信地認為“恩厦取,這步我們已經(jīng)有了”。當我懷疑是插件沒加載成管搪、沒執(zhí)行虾攻、插件不靠譜等等各種嘗試后铡买,有點灰心的時候,不經(jīng)意發(fā)現(xiàn)霎箍,返回的header中真的是沒有Access-Control-Allow-Origin奇钞。為何呢?明明是服務(wù)端已加了的啊漂坏。
去查一下php代碼景埃,發(fā)現(xiàn)我們是從請求header中的Referer中取出http://domain.com:port/ 來生成Access-Control-Allow-Origin(沒有Referer則沒辦法生成)《ケ穑可現(xiàn)在IE的請求中沒有Referer谷徙,倒是有個Origin。再去查查標準文檔 w2c驯绎,才知道完慧,原來Origin才是正確的姿勢。
改了php代碼剩失,世界安靜了屈尼。
后來,我終于在眼淚中明白拴孤,有些軟件脾歧,總那么不可愛
然而,IE8/IE9問題只是“貌似”解決了演熟。當時應(yīng)該也是沒有全面測試鞭执,后來發(fā)現(xiàn),登錄不了绽媒。原來是帶不上Cookie蚕冬!也就是說免猾,XDomainRequest實現(xiàn)的有局限是辕。參見:微軟某程序員的一篇blog。
看來猎提,如果需要兼容IE8获三,是不能完美實現(xiàn)CORS的。
最終的最終锨苏,我們還是無奈地選擇了“js中訪問同域名下的php疙教,nginx做代理(將請求轉(zhuǎn)發(fā)給api)”這種方式。
refs:
http://stackoverflow.com/questions/2870371/why-is-jquerys-ajax-method-not-sending-my-session-cookie
http://www.w3.org/TR/cors/
https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
http://bob.ippoli.to/archives/2005/12/05/remote-json-jsonp/
https://en.wikipedia.org/wiki/JSONP