FastAPI 中介軟體(三) 跨域資源共享中介軟體
作者:麥克煎蛋 出處:https://www.cnblogs.com/mazhiyong/ 轉載請保留這段宣告,謝謝!
跨域資源共享(CORS) 是一種機制,它使用額外的HTTP頭來告訴瀏覽器 讓執行在一個 origin (domain) 上的Web應用被准許訪問來自不同源伺服器上的指定的資源。當一個資源從與該資源本身所在的伺服器不同的域、協議或埠請求一個資源時,資源會發起一個跨域 HTTP 請求。
跨域資源共享標準新增了一組HTTP 首部欄位,允許伺服器宣告哪些源站通過瀏覽器有許可權訪問哪些資源。另外,規範要求,對那些可能對伺服器資料產生副作用的 HTTP 請求方法(特別是GET
以外的 HTTP 請求,或者搭配某些 MIME 型別的POST
請求),瀏覽器必須首先使用OPTIONS
方法發起一個預檢請求(preflight request),從而獲知服務端是否允許該跨域請求。伺服器確認允許之後,才發起實際的HTTP 請求。在預檢請求的返回中,伺服器端也可以通知客戶端,是否需要攜帶身份憑證(包括Cookies和 HTTP 認證相關資料)。
FastAPI利用CORSMiddleware
中介軟體來實現CORS。
一、使用CORSMiddleware
我們通過以下流程在FastAPI應用中使用CORSMiddleware
。
1、匯入CORSMiddleware
。
2、建立允許的origins列表。
3、在應用中引入CORSMiddleware
如果後端支援我們也可以加入以下資訊:
4、鑑權資訊(Authorization headers,Cookies等)。
5、支援的HTTP方法(POST,GET,或者所有"*")。
6、支援的HTTP頭資訊或者所有"*"。
from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware app = FastAPI() origins = [ "http://localhost.tiangolo.com","https://localhost.tiangolo.com","http://localhost","http://localhost:8080",] app.add_middleware( CORSMiddleware,allow_origins=origins,allow_credentials=True,allow_methods=["*"],allow_headers=["*"],) @app.get("/") async def main(): return {"message": "Hello World"}
CORSMiddleware的引數預設值是受限制的,為了在跨域訪問中支援相應的功能,我們應當顯示指定具體引數的的資訊。
CORSMiddleware
支援引數資訊如下:
1、allow_origins
:允許跨域請求的域名列表,例如 [‘https://example.org‘,‘https://www.example.org‘]
或者 [‘*‘]
。
2、allow_origin_regex
:允許跨域請求的域名正則表示式,例如 ‘https://.*\.example\.org‘
。
3、allow_methods
:允許跨域請求的HTTP方法列表,預設為[‘GET‘]
,[‘*‘]
表示允許所有HTTP方法。
4、allow_headers
:跨域請求支援的HTTP頭資訊列表。[‘*‘]
表示允許所有頭資訊。Accept
,Accept-Language
,Content-Language
和 Content-Type頭資訊預設全都支援。
5、allow_credentials
:表示在跨域請求時是否支援cookie,預設為False。
6、expose_headers
:表示對瀏覽器可見的返回結果頭資訊,預設為[]
。
7、max_age
:瀏覽器快取CORS返回結果的最大時長,預設為600(單位秒)。
二、請求種類
瀏覽器將CORS請求分成兩類:簡單請求(Simple requests)和非簡單請求,也叫預檢請求(CORS preflight requests)。
只要同時滿足以下兩大條件,就屬於簡單請求。
(1) 請求方法是以下三種方法之一:
- HEAD
- GET
- POST
(2)HTTP的頭資訊不超出以下幾種欄位:
- Accept
- Accept-Language
- Content-Language
- Last-Event-ID
- Content-Type:只限於三個值
application/x-www-form-urlencoded
、multipart/form-data
、text/plain
凡是不同時滿足上面兩個條件,就屬於非簡單請求。
瀏覽器對這兩種請求的處理,是不一樣的。
1、簡單請求
對於簡單請求,瀏覽器直接發出CORS請求。具體來說,就是在頭資訊之中,增加一個Origin
欄位。
Origin
欄位用來說明,本次請求來自哪個源(協議 + 域名 + 埠)。伺服器根據這個值,決定是否同意這次請求。
在這種情況下,中介軟體會正常傳遞請求資訊,但會在返回結果中包含恰當的CORS頭資訊。
2、預檢請求
非簡單請求是那種對伺服器有特殊要求的請求,比如請求方法是PUT
或DELETE
,或者Content-Type
欄位的型別是application/json
。
非簡單請求的CORS請求,會在正式通訊之前,增加一次HTTP查詢請求,稱為"預檢"請求(preflight)。
瀏覽器先詢問伺服器,當前網頁所在的域名是否在伺服器的許可名單之中,以及可以使用哪些HTTP方法和頭資訊欄位。只有得到肯定答覆,瀏覽器才會發出正式的請求,否則就報錯。
"預檢"請求用的請求方法是OPTIONS
,表示這個請求是用來詢問的。頭資訊裡面,關鍵欄位是Origin
,表示請求來自哪個源。
除了Origin
欄位,"預檢"請求的頭資訊包括兩個特殊欄位。
(1)Access-Control-Request-Method
該欄位是必須的,用來列出瀏覽器的CORS請求會用到哪些HTTP方法,上例是PUT
。
(2)Access-Control-Request-Headers
該欄位是一個逗號分隔的字串,指定瀏覽器CORS請求會額外發送的頭資訊欄位,上例是X-Custom-Header
。
伺服器收到"預檢"請求以後,檢查了Origin
、Access-Control-Request-Method
和Access-Control-Request-Headers
欄位以後,確認是否允許跨源請求,就可以做出迴應。
在這種情況下,中介軟體會攔截請求資訊並且根據是否允許跨域請求返回不同的請求結果資訊。
關於CORS的更多資訊,可訪問Mozilla CORS documentation。
參考文章:
https://www.cnblogs.com/knowledgesea/p/6808411.html
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS