Files
edr-platform/docs/uploads.md

3.0 KiB
Raw Permalink Blame History

Upload size limits

A document upload passes through four independent ceilings. The smallest one wins, so raising a limit in application code changes nothing while a lower limit sits in front of it.

# Layer Limit Where it lives
1 Reverse proxy (client_max_body_size) 50m nginx config on the API host — not in this repo for deployed environments
2 Express JSON/urlencoded body JSON_BODY_LIMIT = 80mb apps/edr-freight-api/src/main.ts
3 Multer multipart (fileSize) DOCUMENT_UPLOAD_MAX_BYTES = 50MB apps/edr-freight-api/src/common/document-upload.options.ts
4 Per-field portal gate (max_size_mb) 50 freight.file_upload_fields, seeded by file-upload-settings.seeder.ts

Layer 4 is the only one the customer sees before uploading — SmartFileInput blocks the file client-side with "File size exceeds the limit of NMB". Layers 13 produce a failed request after the fact.

The nginx layer is the one that bites

nginx defaults client_max_body_size to 1m and answers anything larger with its own HTML error page:

HTTP/1.1 413 Request Entity Too Large
Server: nginx
Content-Type: text/html

Two tells that a 413 came from the proxy rather than the API:

  • the body is nginx's HTML page, not the API's JSON envelope, and
  • curl -w '%{size_upload}' reports 0 — nginx rejects on the Content-Length header, so the body is never transmitted.

This is also why the failure looks like a CORS error in the browser: nginx's error response carries no Access-Control-Allow-Origin header.

Applying it

Add to the server (or location) block fronting the API and reload:

server {
    server_name edrfreightapi-staging.edrsc.com;

    client_max_body_size 50m;

    location / {
        proxy_pass http://freight-api:3001;
        # Large uploads stream for a while; the default 60s read timeout can
        # cut off a slow client mid-body.
        proxy_read_timeout 300s;
        proxy_request_buffering off;
    }
}
nginx -t && nginx -s reload   # -t first: a bad config that reloads takes the site down

On Kubernetes ingress-nginx this is an annotation on the Ingress instead:

nginx.ingress.kubernetes.io/proxy-body-size: 50m

Note that client_max_body_size 0 disables the check entirely — do not use it. An unbounded body is a denial-of-service vector, and layer 3 buffers uploads in memory.

Verifying end to end

512KB should pass the proxy and reach the API; 50MB should too. A 401 here is a success for this purpose — it means the request got past nginx to the API's auth layer.

head -c 52428800 /dev/urandom > big.bin
curl -s -o /dev/null -w 'HTTP %{http_code}  uploaded %{size_upload}\n' \
  -X POST "https://edrfreightapi-staging.edrsc.com/api/companies/<id>/documents" \
  -F "test=@big.bin"
  • 413 with uploaded 0 → the proxy is still capped; layer 1 was not applied.
  • 401/200 with the full byte count → the body made it through.