什么是preflight請求?
preflight愤兵,一個cors預檢請求鹿霸,屬于options請求。該請求會在瀏覽器認為即將要執(zhí)行的請求可能會對服務器造成不可預知的影響時秆乳,由瀏覽器自動發(fā)出懦鼠。
利用預檢請求,瀏覽器能夠知道當前的服務器是否允許執(zhí)行即將要進行的請求屹堰,只有獲得了允許肛冶,瀏覽器才會真正執(zhí)行接下來的請求。
所以双藕,總結有幾點:
- 瀏覽器自動發(fā)出該請求淑趾,不需要用戶干預
- 該請求發(fā)生在用戶發(fā)送的請求之前,只有預檢請求通過忧陪,用戶發(fā)送的請求才能發(fā)送到服務器扣泊,否則拋出CORS錯誤。
prefilght觸發(fā)條件
preflight預檢請求屬于cors規(guī)范的一部分嘶摊,是一種服務器驗證機制延蟹。目前所有瀏覽器都實現(xiàn)了該規(guī)范,但是不免有些瀏覽器會對規(guī)范內(nèi)容進行擴充叶堆。但是必須實現(xiàn)的規(guī)范是:只有以下條件都滿足的情況下才不會發(fā)送預檢請求阱飘,否則會在發(fā)送用戶請求之前發(fā)送預檢請求,以免在獲得允許之前對服務器產(chǎn)生不可預知的影響虱颗。
條件有:
- 請求方法限制
只能使用GET沥匈、POST方法
- 請求頭限制
只能包含九種請求頭:
- Accept
- Accept-language
- Content-Language
- Content-Type
- DPR
- Downlink
- Save-Data
- Viewport-Width
- Width
- Content-type限制
只能包含三種類型:
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
- XMLHttpRequestUpload對象限制
該對象沒有注冊任何事件監(jiān)聽器
- ReadableStream對象限制
請求中不能使用ReadableStream對象
如果以上條件有一條不滿足,瀏覽器則會自動發(fā)起預檢請求
配置preflight請求
瀏覽器自動發(fā)送的預檢請求忘渔,一般采用三個字段來表示:
- Origin:表示當前請求的訪問來源(域名)
- Access-Control-Request-Headers:告知服務器實際請求所攜帶的自定義首部字段
- Access-Control-Request-Methods:告知服務器實際請求所使用的 HTTP 方法
服務器基于從預檢請求獲得的信息來判斷高帖,是否接受接下來的實際請求。
所以服務器同時需要配置preflight響應來回應瀏覽器畦粮,告知瀏覽器是否接受預檢請求散址,主要涉及到三個字段:
- Access-Control-Allow-Origin: 表示允許的訪問來源乖阵。或者可以使用"*" 表示允許所有的訪問來源预麸。這個字段一般用于對跨域請求的支持瞪浸。
- Access-Control-Allow-Headers:表示允許的自定義請求頭。
- Access-Control-Allow-Methods:表示允許的請求方式吏祸。
舉一個例子:
客戶端自定義了一個請求頭uname对蒲,內(nèi)容是admin。但是此時服務器端并沒有預檢請求的處理(這里使用node作為服務器端)
客戶端:
服務器(由于是不同域犁罩,所以實現(xiàn)處理了跨域請求):
結果:
可以看到在發(fā)送用戶請求http://127.0.0.1:8000/server
之前齐蔽,瀏覽器先發(fā)送了一個預檢請求,Type=preflight床估,而觸發(fā)預檢請求的原因是:客戶端在請求頭中添加了自定義請求頭含滴。但是由于服務器端沒有預檢請求的處理,所以瀏覽器沒有得到預檢請求的響應丐巫,就不會處理用戶本身要發(fā)送的請求谈况,因此可以看到/server這個請求出現(xiàn)了CORS ERROR
按照之前所理解的預檢請求,我們可以在服務器端進行配置對該請求的響應:
app.use('/server', (req,res,next) => {
// 設置所有域都可以訪問該域的資源
res.setHeader('Access-Control-Allow-Origin','*');
// 設置允許的自定義請求頭
res.setHeader('Access-Control-Allow-Headers', 'uname');
next();
})
app.post('/server',(req,res) => {
res.send('post');
})
注意:由于preflight請求屬于cors規(guī)范的一部分递胧,因此當前僅當跨域的情況下可能會觸發(fā)preflight碑韵。也即:只有跨域了,且不滿足之前觸發(fā)條件中一條就會觸發(fā)預檢請求缎脾。沒有跨域祝闻,不會觸發(fā)預檢請求。