CORS跨域請求[簡單請求與復雜請求]打賞

CORS即Cross Origin Resource Sharing(跨來源資源共享),通俗說就是我們所熟知的跨域請求。眾所周知,在以前,跨域可以采用代理、JSONP等方式,而在Modern瀏覽器面前,這些終將成為過去式,因為有了CORS。

CORS在最初接觸的時候只大概了解到,通過服務器端設置Access-Control-Allow-Origin響應頭,即可使指定來源像訪問同源接口一樣訪問跨域接口,最近在使用CORS的時候,由于需要傳輸自定義Header信息,發現原來CORS的規范定義遠不止這些。

CORS可以分成兩種:

1、簡單請求
2、復雜請求

一個簡單的請求大致如下

HTTP方法是下列之一

HEAD
GET
POST

HTTP頭信息不超出以下幾種字段

Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type,但僅能是下列之一
application/x-www-form-urlencoded
multipart/form-data
text/plain

任何一個不滿足上述要求的請求,即被認為是復雜請求。一個復雜請求不僅有包含通信內容的請求,同時也包含預請求(preflight request)。

簡單請求的發送從代碼上來看和普通的XHR沒太大區別,但是HTTP頭當中要求總是包含一個域(Origin)的信息。該域包含協議名、地址以及一個可選的端口。不過這一項實際上由瀏覽器代為發送,并不是開發者代碼可以觸及到的。

簡單請求的部分響應頭及解釋如下:

Access-Control-Allow-Origin(必含)- 不可省略,否則請求按失敗處理。該項控制數據的可見范圍,如果希望數據對任何人都可見,可以填寫"*"。
Access-Control-Allow-Credentials(可選) – 該項標志著請求當中是否包含cookies信息,只有一個可選值:true(必為小寫)。如果不包含cookies,請略去該項,而不是填寫false。這一項與XmlHttpRequest2對象當中的withCredentials屬性應保持一致,即withCredentials為true時該項也為true;withCredentials為false時,省略該項不寫。反之則導致請求失敗。
Access-Control-Expose-Headers(可選) – 該項確定XmlHttpRequest2對象當中getResponseHeader()方法所能獲得的額外信息。通常情況下,getResponseHeader()方法只能獲得如下的信息:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
當你需要訪問額外的信息時,就需要在這一項當中填寫并以逗號進行分隔

如果僅僅是簡單請求,那么即便不用CORS也沒有什么大不了,但CORS的復雜請求就令CORS顯得更加有用了。簡單來說,任何不滿足上述簡單請求要求的請求,都屬于復雜請求。比如說你需要發送PUT、DELETE等HTTP動作,或者發送Content-Type: application/json的內容。

復雜請求表面上看起來和簡單請求使用上差不多,但實際上瀏覽器發送了不止一個請求。其中最先發送的是一種"預請求",此時作為服務端,也需要返回"預回應"作為響應。預請求實際上是對服務端的一種權限請求,只有當預請求成功返回,實際請求才開始執行。

預請求以OPTIONS形式發送,當中同樣包含域,并且還包含了兩項CORS特有的內容:

Access-Control-Request-Method – 該項內容是實際請求的種類,可以是GET、POST之類的簡單請求,也可以是PUT、DELETE等等。
Access-Control-Request-Headers – 該項是一個以逗號分隔的列表,當中是復雜請求所使用的頭部。

顯而易見,這個預請求實際上就是在為之后的實際請求發送一個權限請求,在預回應返回的內容當中,服務端應當對這兩項進行回復,以讓瀏覽器確定請求是否能夠成功完成。

復雜請求的部分響應頭及解釋如下:

Access-Control-Allow-Origin(必含) – 和簡單請求一樣的,必須包含一個域。
Access-Control-Allow-Methods(必含) – 這是對預請求當中Access-Control-Request-Method的回復,這一回復將是一個以逗號分隔的列表。盡管客戶端或許只請求某一方法,但服務端仍然可以返回所有允許的方法,以便客戶端將其緩存。
Access-Control-Allow-Headers(當預請求中包含Access-Control-Request-Headers時必須包含) – 這是對預請求當中Access-Control-Request-Headers的回復,和上面一樣是以逗號分隔的列表,可以返回所有支持的頭部。這里在實際使用中有遇到,所有支持的頭部一時可能不能完全寫出來,而又不想在這一層做過多的判斷,沒關系,事實上通過request的header可以直接取到Access-Control-Request-Headers,直接把對應的value設置到Access-Control-Allow-Headers即可。
Access-Control-Allow-Credentials(可選) – 和簡單請求當中作用相同。
Access-Control-Max-Age(可選) – 以秒為單位的緩存時間。預請求的的發送并非免費午餐,允許時應當盡可能緩存。

一旦預回應如期而至,所請求的權限也都已滿足,則實際請求開始發送。

通caniuse.com得知,目前大部分Modern瀏覽器已經支持完整的CORS,但IE直到IE11才完美支持,所以對于PC網站,還是建議采用其他解決方案,如果僅僅是移動端網站,大可放心使用。

CORS跨域請求[簡單請求與復雜請求]
文章《CORS跨域請求[簡單請求與復雜請求]》二維碼
  • 微信打賞
  • 支付寶打賞

已有6條評論

  1. netizen

    牛逼!很清晰明了!感謝大牛.

    2018-09-09 23:55 回復
  2. lant

    這篇文章之前在 阮一峰老師那里看到過類似的, 不過存在的問問題是:
    他寫的是簡單請求是不能超出以下字段?
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type
    你寫的是包含以下字段;

    這里覺著很怪異, 如果說是不超過以下字段的話, 很顯然, 阮一峰的第一個例子中http請求至少有host,connection字段都超出了, 就應該不是簡單請求了,但他卻那這個舉例子

    你這里說包含以下字段, 也不知道是包含幾個 還是所有包含

    2017-09-26 14:48 回復
  3. 飛利浦呼吸機

    好文,謝謝分享!

    2016-08-17 11:07 回復
  4. host1plus

    朋友,交換鏈接嗎?

    2016-05-30 09:19 回復

(必填)

(必填)

(可選)

黑龙江22选5开奖