From 838d10b0840367fd98ed97415d6bc6052012e08b Mon Sep 17 00:00:00 2001 From: jim800121chen Date: Sun, 28 Jun 2026 07:52:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(stage):=20nginx=20=E5=8A=A0=20/preset-model?= =?UTF-8?q?s/=20=E5=8F=8D=E4=BB=A3=E5=88=B0=20api-server=EF=BC=88B8=20stag?= =?UTF-8?q?e=20=E4=BF=AE=E6=AD=A3=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit preset .nef 公用下載端點 GET /preset-models/{id}.nef 由 api-server :3721 串流。nginx.stage.conf 原本無此 location → 落 catch-all 反代到 frontend :3000 → 404。 加 /preset-models/ location(在 /storage 後、catch-all 前),比照 /storage pattern:proxy_buffering off 串流大檔、X-Forwarded-Proto https、安全 header re-add、cache public max-age=86400(preset 公用內容固定)。nginx -t 通過。 配套(同一交付):Dockerfile.stage preset COPY(1d4977a)+ .env.stage 設 VISIONA_PRESET_BASE_URL(git-ignored 不進)。stage e2e 驗證: GET /preset-models/kl520-yolov5-detection.nef → 200 + 7506224 bytes(與原檔一致)。 Co-Authored-By: Claude Opus 4.8 (1M context) --- docker/nginx.stage.conf | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docker/nginx.stage.conf b/docker/nginx.stage.conf index ed3a75b..0ea8cbc 100644 --- a/docker/nginx.stage.conf +++ b/docker/nginx.stage.conf @@ -228,6 +228,44 @@ server { add_header Referrer-Policy "strict-origin-when-cross-origin" always; } + # ============================================================ + # /preset-models/* → api-server :3721 (B8 預設模型 .nef 公用下載) + # + # 7 個系統預設模型 .nef 由 api-server 直接讀 image 內 /app/assets/preset-models + # 串流(GET /preset-models/{id}.nef,不簽 token、preset 公用)。 + # + # ⚠️ 為什麼必須有這條 location: + # 下方 catch-all `location /` 反代到 Next.js frontend (:3000)。若沒有這條, + # /preset-models/* 會落到 frontend → Next 沒有此 route → 404,preset 下載斷掉。 + # 必須在 catch-all 之前用前綴 location 攔下來,導到 api-server。 + # + # 比照 /storage/ pattern(同為 api-server 大檔下載端點): + # - proxy_buffering off:.nef 1-13MB 二進位,串流直送、不在 nginx 全 buffer 後才回 + # - X-Forwarded-Proto https:backend 組對外 absolute URL 時判斷正確 + # - server-level client_max_body_size 100M 是「上傳」上限,對下載無影響 + # - cache:preset 公用、內容固定(baked 進 image,id 對應檔不變)→ 允許瀏覽器 + # 快取 1 天減少重複下載大檔;非用戶私有資料、無 PII,不需 no-store。 + # ============================================================ + location /preset-models/ { + proxy_pass http://visiona_api; + proxy_http_version 1.1; + proxy_buffering off; + + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Connection ""; + + # preset 公用、內容固定 → 可被瀏覽器快取(非敏感、非用戶私有) + expires 1d; + add_header Cache-Control "public, max-age=86400" always; + + # nginx location level 的 add_header 會完全覆蓋 server level — re-add 安全 header + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + } + # ============================================================ # /tunnel/connect — WebSocket upgrade,由 visionA Agent 連入 # 要 long-lived(24h 心跳級別);拉到 86400s。