From 81a32a5bf89771f2cba716984f28cbe85f61154d Mon Sep 17 00:00:00 2001 From: jim800121chen Date: Thu, 9 Jul 2026 06:00:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(stage):=20nginx=20=E5=8A=A0=20/ws/=20locat?= =?UTF-8?q?ion=EF=BC=88=E6=8E=A8=E8=AB=96=20inference=20WS=20+=20=E5=85=B6?= =?UTF-8?q?=E9=A4=98=20/ws/*=20stub=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 兩個 server block(公網 stage-9527 + 內網 IP 直連 192.168.0.130)各加 一條 location /ws/ → proxy_pass api-server(:3721)。缺這條時 /ws/* 會落到 catch-all → Next.js → 404,擋住前端推論頁 WS 握手。 - WS upgrade 三要素(http/1.1 + Upgrade + Connection $connection_upgrade) - 長 timeout 86400s + proxy_buffering off(比照 /tunnel/connect) - 不影響既有 /tunnel/connect(不同 path 前綴、互不 shadow) - 兩 block header 對齊(含 X-Forwarded-Host) 驗證:/ws/devices/test-id/inference 不帶 cookie → 401(過 backend auth) 不再 404;/tunnel/connect 回歸 401;preset 下載 200/206;demo 設定保留。 Co-Authored-By: Claude Opus 4.8 (1M context) --- docker/nginx.stage.conf | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/docker/nginx.stage.conf b/docker/nginx.stage.conf index d779457..e18b363 100644 --- a/docker/nginx.stage.conf +++ b/docker/nginx.stage.conf @@ -292,6 +292,45 @@ server { proxy_set_header X-Forwarded-Proto https; } + # ============================================================ + # /ws/* → api-server :3721 (推論 inference WS + 既有 pairing/events/system WS) + # + # ⚠️ 為什麼必須有這條 location: + # 下方 catch-all `location /` 反代到 Next.js frontend (:3000)。若沒有這條, + # /ws/devices/:id/inference 等所有 /ws/* 會落到 frontend → Next 沒有此 route + # → 404,前端推論頁的 WS 握手斷掉。必須在 catch-all 之前用前綴 location 攔下, + # 導到 api-server (:3721),該處掛 wsAuthGroup(/ws/devices/:id/inference 需 auth) + # 與 registerWebSocketStubs(其餘 /ws/* 目前 501 stub)。 + # + # 與 /tunnel/connect 的關係:兩者是不同 path 前綴(/ws/ vs /tunnel/connect), + # nginx 前綴 location 各自最長匹配、互不 shadow。/ws/ 不會吃到 /tunnel/connect。 + # + # WS upgrade 三要素 + 長 timeout + buffering off,比照 /tunnel/connect。 + # $connection_upgrade 繼承自 http-context map(檔頭 38-41 行)。 + # cookie 由 proxy_pass 預設透傳(inference WS 走 cookie/session auth)。 + # ============================================================ + location /ws/ { + proxy_pass http://visiona_api; + proxy_http_version 1.1; + + # WebSocket upgrade headers + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + # 推論 WS 為 long-lived 串流;拉長 timeout(比照 /tunnel/connect) + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; + + # 不 buffer,避免延遲 WS 訊框 + proxy_buffering off; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-Host $host; + } + # ============================================================ # Next.js hashed static assets — 永久 cache # /_next/static/{hash}.js 等 @@ -480,6 +519,29 @@ server { proxy_set_header X-Forwarded-Proto http; } + # ── /ws/* → api-server :3721(推論 inference WS + 其餘 /ws/* stub)── + # 完整比照 stage-9527 block 的 /ws/ 設定:http/1.1 + Upgrade + Connection + # + 86400s timeout + buffering off。$connection_upgrade 繼承自 http-context map。 + # 不會 shadow 上面的 /tunnel/connect(不同 path 前綴)。 + location /ws/ { + proxy_pass http://visiona_api; + proxy_http_version 1.1; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; + + proxy_buffering off; + + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto http; + proxy_set_header X-Forwarded-Host $host; + } + # ── Next.js hashed static(內網瀏覽器用)── location /_next/static/ { proxy_pass http://visiona_frontend;