FastAPI CORS 跨來源資源共用
CORS (Cross-Origin Resource Sharing) 是一種瀏覽器的安全機制。
當你的前端 (例如 Vue, React) 跑在 http://localhost:3000,而後端 FastAPI 跑在 http://localhost:8000 時,如果不設定 CORS,瀏覽器會攔截前端發出的請求,並顯示類似 Access-Control-Allow-Origin 的錯誤。
使用 CORSMiddleware
FastAPI 提供了 CORSMiddleware 來解決這個問題。
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",
"http://localhost:3000", # 常見的前端開發 Port
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins, # 允許的來源
allow_credentials=True, # 是否允許攜帶 Cookie 等憑證
allow_methods=["*"], # 允許的 HTTP 方法 (GET, POST, etc.),"*" 代表全部允許
allow_headers=["*"], # 允許的 HTTP Header,"*" 代表全部允許
)
@app.get("/")
async def main():
return {"message": "Hello World"}
參數說明
allow_origins:一個允許的來源 URL 列表 (字串的 List)。例如['http://localhost:3000']。如果你想允許所有來源,可以使用['*']。allow_origin_regex:使用正規表達式來匹配允許的來源。allow_credentials:布林值。設定為True代表允許瀏覽器在跨域請求中傳送 Cookie (例如用於 Session 登入)。注意:若設為 True,allow_origins不能為['*'],必須明確指定來源。allow_methods:允許的 HTTP 方法列表,如['GET', 'POST']。預設為['GET']。使用['*']代表允許所有。allow_headers:允許的 HTTP Header 列表。預設為[]。使用['*']允許所有 Header (包括前端自訂的 Header)。
常見問題
為什麼使用了 ['*'] 還是報錯?
如果你設定了 allow_credentials=True,標準規定 allow_origins 不能是 ['*']。你必須明確列出所有允許的 Domain。
什麼是 Preflight Request (OPTIONS)?
對於某些「非簡單請求」(例如帶有自訂 Header 或 Content-Type 為 application/json 的 POST),瀏覽器會先發送一個 OPTIONS 請求來詢問伺服器是否允許。CORSMiddleware 會自動幫你處理這個 OPTIONS 請求並回傳正確的 Header。
總結
- 只要是前後端分離開發,幾乎一定會遇到 CORS 問題。
- 使用
CORSMiddleware並正確設定allow_origins即可解決。 - 開發環境可以開得比較寬鬆,生產環境請務必限制來源以保安全。