CORS(Cross-Origin Resource Sharing)
CORS 是一種瀏覽器安全特性,用於限制來自不同域的網頁腳本如何與伺服器資源進行互動。 如果你在構建一個前後端分離的應用,前端和後端位於不同的域(或端口),你就需要配置 CORS。
為什麼? 簡單來講,如果不限制請求的來源,那只要知道 url 的不明來源都可以發請求,而且伺服器還很聽話的把資料傳給對方,如果涉及敏感資料,容易有安全性的問題。
在 FastAPI 中配置 CORS(跨域資源共享)非常簡單。
Fastapi codes(後端)
下面這段 code 示範沒有設置 CORS 的情況下,前端會 發生什麼錯誤。
功能描述:主要是有個 Item 的 class,可以讓前端發請求做 CRUD 的操作。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
id: int
name: str
description: str = None
items = {}
@app.post("/items/")
def create_item(item: Item):
if item.id in items:
raise HTTPException(status_code=400, detail="Item already exists")
items[item.id] = item
return item
@app.get("/items/{item_id}")
def read_item(item_id: int):
if item_id not in items:
raise HTTPException(status_code=404, detail="Item not found")
return items[item_id]
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
if item_id not in items:
raise HTTPException(status_code=404, detail="Item not found")
items[item_id] = item
return item
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
if item_id not in items:
raise HTTPException(status_code=404, detail="Item not found")
del items[item_id]
return {"detail": "Item deleted"}
前端 codes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<!DOCTYPE html>
<html>
<head>
<title>FastAPI CRUD Operations</title>
<script>
const baseURL = 'http://localhost:8000';
async function createItem() {
const id = document.getElementById('create-id').value;
const name = document.getElementById('create-name').value;
const description = document.getElementById('create-description').value;
const response = await fetch(`${baseURL}/items/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: parseInt(id), name: name, description: description })
});
const result = await response.json();
alert(JSON.stringify(result));
}
async function readItem() {
const id = document.getElementById('read-id').value;
const response = await fetch(`${baseURL}/items/${id}`, { method: 'GET' });
const result = await response.json();
alert(JSON.stringify(result));
}
async function updateItem() {
const id = document.getElementById('update-id').value;
const name = document.getElementById('update-name').value;
const description = document.getElementById('update-description').value;
const response = await fetch(`${baseURL}/items/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: parseInt(id), name: name, description: description })
});
const result = await response.json();
alert(JSON.stringify(result));
}
async function deleteItem() {
const id = document.getElementById('delete-id').value;
const response = await fetch(`${baseURL}/items/${id}`, { method: 'DELETE' });
const result = await response.json();
alert(JSON.stringify(result));
}
</script>
</head>
<body>
<h1>FastAPI CRUD Operations</h1>
<h2>Create Item</h2>
<label>ID:</label><input type="text" id="create-id"><br>
<label>Name:</label><input type="text" id="create-name"><br>
<label>Description:</label><input type="text" id="create-description"><br>
<button onclick="createItem()">Create</button><br>
<h2>Read Item</h2>
<label>ID:</label><input type="text" id="read-id"><br>
<button onclick="readItem()">Read</button><br>
<h2>Update Item</h2>
<label>ID:</label><input type="text" id="update-id"><br>
<label>Name:</label><input type="text" id="update-name"><br>
<label>Description:</label><input type="text" id="update-description"><br>
<button onclick="updateItem()">Update</button><br>
<h2>Delete Item</h2>
<label>ID:</label><input type="text" id="delete-id"><br>
<button onclick="deleteItem()">Delete</button><br>
</body>
</html>
透過 OpenAPI 自動生成互動文件,先加入資料,再讓前端去讀
加入一筆 Item 資料
可以看到成功加入
現在透過前端去 Get,可以看到 server ok
但前端有 CORS 錯誤
在加入以下片段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
# 配置 CORS 中間件
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost"], # 允許的來源
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
#1. allow_origins:一個包含允許來源(origin)的列表。可以使用 ["*"] 來允許所有來源,但在生產環境中應盡量避免。
#2. allow_credentials:是否允許發送包含身份驗證信息的請求(如 cookies 或 HTTP 認證信息)。
#3. allow_methods:一個包含允許的 HTTP 方法的列表,如 ["GET", "POST"]。可以使用 ["*"] 來允許所有方法。
#4. allow_headers:一個包含允許的 HTTP 頭的列表,如 ["Content-Type", "Authorization"]。可以使用 ["*"] 來允許所有頭。
查詢剛剛的資料
更新該筆資料
再查一次,確定更新成功
刪除資料
再查一次,該筆資料消失
以上,這樣完整的 CRUD 都做到了!