簡單請求與複雜請求的概念
在涉及到CORS(跨域)的請求中,我們會把請求分為簡單請求和複雜請求。滿足以下條件的請求即為簡單請求:
請求方法:GET、POST、HEAD
除了以下的請求頭字段之外,沒有自定義的請求頭,是可以有其它標準請求頭的
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type的值只有以下三種(Content-Type一般是指在post請求中,get請求中設置沒有實際意義)
text/plain
multipart/form-data
application/x-www-form-urlencoded
非簡單請求即為複雜請求。複雜請求我們也可以稱之為在實際進行請求之前,需要發起預檢請求的請求。
預檢請求(OPTIONS請求)
為什麼要發預檢請求
我們都知道瀏覽器的同源策略,就是出於安全考慮,瀏覽器會限制從腳本發起的跨域HTTP請求,像XMLHttpRequest和Fetch都遵循同源策略。
瀏覽器限制跨域請求一般有兩種方式:
- 瀏覽器限制發起跨域請求
- 跨域請求可以正常發起,但是返回的結果被瀏覽器攔截了
一般瀏覽器都是第二種方式限制跨域請求,那就是説請求已到達服務器,並有可能對數據庫裏的數據進行了操作,但是返回的結果被瀏覽器攔截了,那麼我們就獲取不到返回結果,這是一次失敗的請求,但是可能對數據庫裏的數據產生了影響。
為了防止這種情況的發生,規範要求,對這種可能對服務器數據產生不可預測影響的HTTP請求方法,瀏覽器必須先使用OPTIONS方法發起一個預檢請求,從而獲知服務器是否允許該跨域請求:如果允許,就發送帶數據的真實請求;如果不允許,則阻止發送帶數據的真實請求。
預檢請求的特殊性
一、OPTIONS不會攜帶請求參數和cookie,也不會對服務器數據產生副作用
二、Access-Control-Request-Method和Access-Control-Request-Headers
//預檢請求請求頭
OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
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
Connection: keep-alive
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
首部字段 Access-Control-Request-Method 告知服務器,實際請求將使用 POST 方法。首部字段 Access-Control-Request-Headers 告知服務器,實際請求將攜帶兩個自定義請求首部字段:X-PINGOTHER 與 Content-Type。服務器據此決定,該實際請求是否被允許。
三、OPTIONS請求響應頭
響應頭
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
首部字段 Access-Control-Allow-Methods 表明服務器允許客户端使用 POST,GET 和 OPTIONS 方法發起請求。
首部字段Access-Control-Allow-Headers 表明服務器允許請求中攜帶字段X-PINGOTHER 與Content-Type。與 Access-Control-Allow-Methods一樣,Access-Control-Allow-Headers的值為逗號分割的列表。
最後,首部字段
Access-Control-Max-Age 表明該響應的有效時間為 86400 秒,也就是 24 小時。在有效時間內,瀏覽器無須為同一請求再次發起預檢請求。請注意,瀏覽器自身維護了一個最大有效時間,如果該首部字段的值超過了最大有效時間,將不會生效。
預檢請求完成之後,發送實際請求