Repository navigation
v1.2.0 開放瀏覽器端直接呼叫。起因是 docs 站的「Tor 中繼地球儀」是一頁靜態頁面,要加上「即時更新」按鈕就必須讓瀏覽器直接 fetch onionoo.anoni.net,而 1.1.0 的 CORS 預設清單是空的,middleware 根本沒有掛上去。
CORS 白名單
新增 CORS_ALLOW_ORIGINS,逗號分隔,與 pulse/backend 既有的變數同名同格式,兩個服務的設定方式一致。
預設清單涵蓋 docs 站實際被服務的位置:
| Origin | 用途 |
|---|---|
https://anoni.net |
clearnet docs 站 |
http://docs.anoninetru5tflukgfaehun7q6khowgmymcff3gtk5oyesqazhmfxtyd.onion |
onion 鏡像 |
http://127.0.0.1:8000 |
本機 mkdocs serve |
http://localhost:8000 |
本機 mkdocs serve |
兩種寫法不對稱是有原因的。clearnet 的 docs 掛在路徑底下(https://anoni.net/docs/),所以 origin 是裸的 apex。onion 鏡像則是同一把 onion key 的子網域,那是它自己的 origin,必須單獨列。
其餘設定:
allow_credentials保持False。所有路由都不看 cookie 與Authorization,關掉它可以確保瀏覽器不會在跨來源呼叫上夾帶環境憑證,也讓之後要放寬白名單時少一層顧慮。allow_methods只開GET與OPTIONS。這是唯讀代理,GET覆蓋所有路由,OPTIONS給 preflight。expose_headers開放X-Request-ID與Last-Modified,讓前端能讀到請求編號與上游資料時間。- 設成
CORS_ALLOW_ORIGINS=""即可完全關閉 CORS,middleware 不會掛載。
服務代理的是 Onionoo 的公開唯讀資料,開放的風險低,白名單的作用比較接近限制誰能花掉我們的上游預算。即使如此仍然走環境變數列舉,不寫死 *,之後要放寬比要收緊容易。
無條件輸出 Vary: Origin
新增 app/middleware.py 的 VaryOriginMiddleware,掛在最外層,保證每個 HTTP 回應都帶 Vary: Origin。
Starlette 只在 Origin 命中白名單那條分支加這個標頭(allow_explicit_origin() 內),沒帶 Origin 或被拒絕的請求不會有。實測 Starlette 1.3:
| 請求 | 1.1.0 的 Vary |
|---|---|
| 命中白名單的 origin | Origin, Accept-Encoding |
| 不在白名單的 origin | 只有 Accept-Encoding |
沒帶 Origin |
只有 Accept-Encoding |
後兩者會與命中的請求共用快取鍵。前面有 CDN 或反向代理時,一個沒有 Access-Control-Allow-Origin 的回應可能被 replay 給合法來源的瀏覽器,反過來也一樣。
middleware 是冪等的,CORS 已經寫過就不動它,看到 Vary: * 也不會畫蛇添足。用 add_vary_header() 追加而非覆寫,所以與 GZipMiddleware 的 Accept-Encoding 能並存。
CORS_ALLOWED_ORIGINS 仍然接受
1.0.0 用的是 CORS_ALLOWED_ORIGINS。改名後舊名稱透過 AliasChoices 繼續生效,並在 startup 印出 deprecation 警告。
這一層是必要的:Settings 的 extra="ignore" 會默默吞掉不認識的變數名稱,自架者升級後唯一的症狀會是瀏覽器端 CORS 失敗,服務端一行 log 都沒有。兩個名稱同時存在時以新名稱為準。舊名稱會在未來版本移除。
startup log 也開始印出生效中的白名單。瀏覽器端的 CORS 失敗,與服務單純掛掉,症狀長得一模一樣,把清單放進啟動訊息可以省掉一輪猜測。
README 修正過期的預設值
1.1.0 動過的設定值沒有同步到 README,一併補上:
MAX_LIMIT從文件寫的200更正為20000- 補上
MAX_LIMIT_UNTRIMMED(預設200,未帶fields=時超過會回 422,未投影的全量 payload 約 90 MB) CACHE_MAXSIZE從1024更正為128- 記憶體估算從 ~500 MiB 修正為 ~64 MiB
自架注意
預設白名單是 anoni.net 的部署位置。自架時請換成你自己的 origin,否則等於幫別人的站台開了門。
另外,從 onion 鏡像讀 docs 的人按下「即時更新」時,那仍然是一個經由 exit node 出去的 clearnet 請求。這是頁面設計的既有行為,與本次改動無關,但值得知道。
升級注意
對既有呼叫端沒有破壞性變更。1.1.0 的 CORS 預設清單是空的,middleware 沒有掛載,所以先前所有跨來源請求本來就會被瀏覽器擋下。升級後預設會開始放行上表那四個 origin。
自架者若要維持完全不開 CORS 的行為,設 CORS_ALLOW_ORIGINS="" 即可。
gzip 壓縮未受影響。實測線上 1.2.0,帶五個欄位的 limit=20000 回應 1.92 MB 壓到 421 KB,Content-Encoding: gzip 與 Vary: Origin, Accept-Encoding 同時存在。
安裝
pip install onionoo-fastapi==1.2.0
# 或
uv add onionoo-fastapi==1.2.0docker pull ghcr.io/anoni-net/onionoo-fastapi:1.2.0What's Changed
Full Changelog: v1.1.0...v1.2.0