fix: stream HTTP 200 heartbeat before upload body to prevent proxy timeouts
Build and Deploy Verso / deploy (push) Has been cancelled

Uploads from slow connections consistently fail with 502 after ~60-120s
because an upstream proxy (Traefik or cloud load-balancer) has a
"first response byte" deadline that fires before the request body arrives.

Fix: add startStreamingResponse middleware (after auth, before multer)
that immediately writes HTTP 200 + Transfer-Encoding: chunked + '\n'.
With proxy_request_buffering off in Nginx, this reaches the proxy at T≈0,
so no timeout triggers. The upload body continues streaming; multer writes
to disk; the actual JSON result arrives as the final chunk. Periodic
heartbeat '\n' writes every 30s keep response-idle timeouts at bay too.

Client-side: override Uppy's getResponseData/validateStatus to trim
leading whitespace before JSON.parse so the extra '\n' bytes are ignored.
Server-side: sendUploadResponse() helper handles both streaming mode
(res.headersSent → res.end(json)) and normal mode (res.status(N).json()).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
claude
2026-06-14 08:59:02 +00:00
parent 8f372d13f8
commit 94d3764c05
4 changed files with 77 additions and 19 deletions
+7 -2
View File
@@ -10,16 +10,21 @@ server {
}
# File upload endpoints: extended timeouts for large files on slow connections.
# client_body_timeout 15m is set globally in nginx.conf.template; repeated
# here explicitly and client_max_body_size raised to 550m for this path.
# proxy_request_buffering off: forward the request body to Node.js immediately
# rather than buffering first, so Node.js can send a keepalive response byte
# before the full body arrives (preventing upstream proxy "first-byte" timeouts).
# proxy_buffering off: forward that keepalive byte to Traefik/LB without delay.
location ~ ^/project/[^/]+/upload$ {
proxy_pass http://127.0.0.1:4000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_request_buffering off;
proxy_buffering off;
proxy_read_timeout 15m;
proxy_send_timeout 15m;
send_timeout 15m;
client_body_timeout 15m;
client_max_body_size 550m;
}