網址導向
FastAPI 可使用 Starlette 提供的 `RedirectResponse`,讓瀏覽器收到重新導向回應後,自動前往另一個網址。
## 基本情境:舊網址導向新網址
例如網站將 `/old-page` 搬到 `/new-page`:
```python
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/old-page")
def old_page():
return RedirectResponse(
url="/new-page",
status_code=301
)
@app.get("/new-page")
def new_page():
return {"message": "這是新頁面"}
```
使用者請求:
```text
GET /old-page
```
FastAPI 回應:
```text
301 Moved Permanently
Location: /new-page
```
瀏覽器接著會前往:
```text
/new-page
```
常見狀態碼:
- `302`:暫時導向
- `301`:永久導向,瀏覽器與搜尋引擎可能會快取
- `307`:暫時導向,保留原本的 HTTP method
- `308`:永久導向,保留原本的 HTTP method
如果只是一般的 GET 頁面搬移,常用 `301` 或 `302`。
---
## 變化情境:依登入狀態導向不同網址
例如使用者造訪 `/profile`:
- 已登入:前往個人頁面
- 未登入:導向登入頁,並附上登入後要返回的位置
```python
from fastapi import FastAPI, Request
from fastapi.responses import RedirectResponse
app = FastAPI()
def is_logged_in(request: Request) -> bool:
# 實際應用中可從 Cookie、Session 或 Token 判斷
return request.cookies.get("logged_in") == "true"
@app.get("/profile")
def profile(request: Request):
if not is_logged_in(request):
return RedirectResponse(
url="/login?next=/profile",
status_code=302
)
return {"message": "這是使用者個人頁面"}
@app.get("/login")
def login():
return {"message": "請先登入"}
```
當未登入使用者造訪:
```text
/profile
```
會被導向:
```text
/login?next=/profile
```
登入成功後,系統可以根據 `next` 參數將使用者送回 `/profile`。
### 安全注意事項
如果 `next` 或重新導向網址來自使用者輸入,應限制只能導向本站允許的路徑,避免 **Open Redirect**,例如攻擊者讓網站導向到釣魚網站:
```text
/login?next=https://malicious.example.com
```
因此實務上應檢查網址是否為本站內部路徑或允許的網域。
相關學習地圖、教學課程
Python 後端工程、資料庫