Skip to content

Nginx Proxy Issue: In production, TUS resumable upload initialization succeeds, but chunk upload fails. #219

@horner

Description

@horner

Summary

In production, TUS resumable upload initialization succeeds, but chunk upload fails.
POST /uploads returns 201, then PATCH /uploads/:id returns 405 Not Allowed.

This breaks PulseCam chunked uploads and surfaces an upload failure alert in the UI.

Affected Environment

  • Environment: production (nginx proxy in front of Node/Express)
  • URL: https://pulseclip.os.mieweb.org/
  • Date observed: 2026-03-02
  • Browser test via Playwright MCP

Steps to Reproduce

  1. Open https://pulseclip.os.mieweb.org/
  2. Start an upload flow that uses TUS resumable uploads.
  3. Observe network requests.
Image

Actual Behavior

  • POST /uploads -> 201 Created
  • PATCH /uploads/{uploadId} -> 405 Not Allowed
  • Browser console error:
    Failed to load resource: the server responded with a status of 405 ()
  • UI shows chunk upload failure and retry option.

Expected Behavior

PATCH /uploads/{uploadId} should be proxied to backend and return TUS-compliant response (e.g., 204 with updated Upload-Offset) until upload completion.

Evidence

Observed request sequence:

  • GET /api/about -> 200
  • GET /api/providers -> 200
  • GET /api/featured -> 200
  • POST /uploads -> 201
  • PATCH /uploads/{id} -> 405

Suspected Root Cause

Proxy/routing mismatch at nginx:

  • /uploads create route is reachable (POST works),
  • but method handling for /uploads/:id likely blocks or misroutes PATCH.
    Possibilities:
  • limit_except excludes PATCH
  • /uploads matched by static location instead of upstream proxy
  • method whitelist does not include TUS methods (OPTIONS, HEAD, PATCH, DELETE)

Scope / Impact

  • PulseCam mobile upload flow is functionally broken in production for resumable uploads.
  • Standard non-TUS file upload may still work (separate /api/upload path).

Proposed Fix

Update nginx config for /uploads to:

  1. Proxy all /uploads traffic to Node/Express upstream
  2. Allow TUS methods: OPTIONS, POST, HEAD, PATCH, DELETE
  3. Keep request body streaming/size settings compatible with chunked uploads
  4. Preserve TUS headers (e.g., Tus-Resumable, Upload-Offset, Upload-Length, Upload-Metadata)

Acceptance Criteria

  • POST /uploads returns 201 in production
  • PATCH /uploads/:id returns non-405 and advances Upload-Offset
  • Full TUS upload completes successfully end-to-end
  • No console errors related to /uploads/:id 405
  • UI upload flow no longer shows chunk upload failure

Optional Follow-ups

  • Add proxy integration test or smoke check for TUS methods
  • Add production health/synthetic check for resumable upload route and methods
  • Document required reverse-proxy method support for TUS in deployment docs

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions