S3 PDF Upload
Instead of returning the generated document in the response body, the API can upload it directly to object storage using a presigned URL you supply per request. This avoids round-tripping large files through your application and is handy for serverless callers.
How it works
Section titled “How it works”Send an X-Upload-Url header containing a presigned PUT URL on any generating endpoint —
POST /render/html, POST /render/url, POST /render/template, or POST /render. The API then
PUTs the result to that URL with the correct Content-Type (application/pdf, or
image/png / image/jpeg for /render) and replies 204 No Content with an empty body. For
PDFs the X-Document-UUID response header is still set, so you can correlate the stored
file.
On PDF render endpoints, do not send Accept: application/json with X-Upload-Url; JSON
negotiation returns the PDF inline as base64 and is only available when the API response body
carries the result. The image /render endpoint does not have a JSON validation response mode.
You generate the presigned URL yourself (for example with the AWS SDK’s put_object presigner),
so the API never needs storage credentials — it only performs the upload.
Example
Section titled “Example”curl -i -X POST http://localhost:8080/render/html \ -H "Content-Type: application/json" \ -H "X-Upload-Url: https://my-bucket.s3.amazonaws.com/out.pdf?X-Amz-Algorithm=...&X-Amz-Signature=..." \ -d '{"html":"<html lang=\"en\"><head><title>Doc</title></head><body><h1>Hi</h1></body></html>"}'# HTTP/1.1 204 No ContentThe presigned URL must accept a PUT with the matching content type. Omit the header to get the
document back inline as usual.
Configuration
Section titled “Configuration”| Variable | Default | Meaning |
|---|---|---|
UPLOAD_ENABLED | true | Enable or disable the X-Upload-Url feature |
UPLOAD_TIMEOUT | 30000 | Upload request timeout in milliseconds |
UPLOAD_ALLOWED_DOMAINS | — | Optional comma-separated allowlist of upload hosts; empty means any public host |
docker run -p 8080:8080 \ -e UPLOAD_ALLOWED_DOMAINS="my-bucket.s3.amazonaws.com" \ ghcr.io/bambamboole/pdf-ua-api:latestSecurity
Section titled “Security”The upload URL is validated with the same guard as asset fetching: redirects are never followed
so they can’t bypass the guard. Private, loopback, and link-local addresses are rejected only
when TRUST_PRIVATE_HOSTS=false (the guard is off by default); enable it on internet-facing
deployments. Set UPLOAD_ALLOWED_DOMAINS to restrict uploads to specific hosts.
Responses
Section titled “Responses”204 No Content— the document was uploaded successfully.400 Bad Request— uploads are disabled (UPLOAD_ENABLED=false), or the URL is invalid or blocked by the SSRF guard / allowlist.502 Bad Gateway— the upload target rejected thePUT(non-2xx) or was unreachable.