3.0 KiB
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
1–3 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 theContent-Lengthheader, 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"
413withuploaded 0→ the proxy is still capped; layer 1 was not applied.401/200with the full byte count → the body made it through.