什么情況下會發起Options請求?
引言
在Web開發中,HTTP協議扮演著至關重要的角色,它定義了客戶端和服務器之間如何交換數據。本文將詳細介紹HTTP協議中的OPTIONS請求方法,并闡述其在實際應用中的重要性。
什么是OPTIONS請求?
首先,我們需要了解什么是OPTIONS請求。OPTIONS是HTTP協議中定義的一種請求方法。這些方法包括GET、POST、PUT、DELETE、HEAD、CONNECT、TRACE以及我們這里討論的OPTIONS。每種方法都代表不同類型的請求行為。
OPTIONS請求的主要目的不是獲取響應主體內容,而是獲取信息。這些信息包括服務器支持哪些HTTP方法,或者針對某個URL的跨域資源共享(CORS)設置等。
OPTIONS請求具體做什么?
那么,OPTIONS具體做什么呢?簡單來說,當一個客戶端發送一個OPTIONS請求到服務器時,它在尋求信息——特別地,它想知道針對某個資源服務器允許哪些HTTP方法。
例如,在瀏覽器發起一個非簡單跨域請求之前(比如PUT或DELETE等),會先發送一個預檢(preflight) OPTIONS 請求到目標URL。如果服務器響應表示接受此類操作,則瀏覽器才會發出實際的非簡單跨域請求;否則瀏覽器將阻止該次網絡交互。
預檢CORS配置通過以下兩個步驟完成:
- 瀏覽器首先向服務器發送帶有Origin頭和Access-Control-Request-Method頭(指定真正要使用的HTTP動詞)以及可能帶有Access-Control-Request-Headers頭(指定真正要使用的自定義頭部字段) 的 OPTIONS 請求。
- 服務端收到預檢CORS配置后進行判斷處理,并返回狀態碼200以及一系列Access-Control-Allow-*頭部字段來告訴瀏覽器是否可以進行下一步操作。
哪些情況需要發送預檢CORS配置?
然而,并不是所有情況下都需要發送預檢CORS配置。當滿足以下所有條件時被稱為"簡單請求":
- 方法為GET, HEAD 或 POST。
- HTTP 的 header 信息不超過以下幾種字段:Accept, Accept-Language, Content-Language, Content-Type (但只限于三個值application/x-www-form-urlencoded, multipart/form-data 或 text/plain)
對于"簡單請求"而言,瀏覽器直接發出CORS請求,在Header 中加入Origin字段即可。
預檢請求包含以下頭信息:
- Access-Control-Request-Method:實際要發送給服務器的HTTP方法
- Access-Control-Request-Headers:實際要發送給服務器額外添加到標準CORS協議上header字段
值得注意是,“復雜”或者“非簡單”的跨域POST請求數字類型Content-Type值必須為: application/x-www-form-urlencoded,multipart/form-data 或 text/plain其中之一,否則就會觸發預檢請求。
如果服務器允許該跨域操作,則返回狀態碼200,并在響應頭中加入Access-Control-Allow-Origin等字段;否則返回相應錯誤信息。只有當預檢成功后才會發起真正的HTTP請求。
OPTIONS請求的另一個重要用途是CORS預檢。這是一種由CORS(Cross-Origin Resource Sharing, 跨來源資源共享)機制提供的安全措施。在跨域請求中,瀏覽器為了保護用戶信息不被惡意網站獲取,在發送真正的請求前,會先使用OPTIONS方法發出一個HTTP預檢請求到服務器,以確認真正的請求是否安全被服務器接收。
應用
如果你正在使用Koa框架,你可以使用koa-cors中間件來處理跨域和OPTIONS請求。以下是一個簡單示例:
const Koa = require('koa');
const cors = require('@koa/cors');
const app = new Koa();
app.use(cors({
origin: '*', // 允許所有源
allowMethods: ['GET', 'POST', 'DELETE', 'PUT'], // 允許的HTTP方法
allowHeaders: ['Content-Type'], // 允許的頭部字段
}));
app.listen(3000);
在這個示例中,我們通過cors中間件設置了允許所有源、指定HTTP方法以及Content-Type頭部。
注意:實際情況下,出于安全考慮,不建議將origin設置為"*"(允許所有源),而應該明確指定允許哪些源進行跨域請求。
一個非簡單請求的預檢請求通過之后,其他所有非簡單請求都不用預檢了嗎?
不完全是這樣的。預檢請求的結果會被瀏覽器緩存一段時間,這個時間長度由服務器端在響應預檢請求時通過Access-Control-Max-Age頭部字段來指定。也就是說,在這個時間范圍內,對于相同的URL、相同的請求方法和頭部信息,瀏覽器不會再次發送預檢請求。
但是如果超過了Access-Control-Max-Age所設定的時間,或者你發起了一個新的、與之前不同URL、方法或頭部信息的非簡單請求,那么瀏覽器仍然需要發送新的預檢請求。
因此,并非所有非簡單請求都只需要一次預檢。具體還取決于服務器對CORS策略設置以及是否超出了緩存有效期等因素。
寫在最后
在實際應用中,OPTIONS請求主要用于兩個方面:
- CORS 預檢請求:當我們在進行跨域操作并且滿足一定條件(如請求方法非GET/HEAD/POST、Content-Type非application/x-www-form-urlencoded、multipart/form-data或text/plain等)時,瀏覽器會自動發送一個OPTIONS預檢請求。這是為了確認實際的HTTP請求是否可以被服務器接受。此時,服務器需要正確響應OPTIONS請求,并在響應頭中包含正確的CORS相關信息。
- 探索服務器能力:你也可以直接使用OPTIONS來查詢服務器支持的HTTP方法。例如,你可能對一個API端點發出OPTIONS請求以查看它支持什么樣的HTTP方法。
總結起來說,你可以把OPTIONS看作是詢問“我能做什么”,而不直接執行具體操作。理解并合理使用OPTIONS方法,對于我們進行Web開發和維護工作有著重要意義。