Files
papercrate/docs/s3_cors_presign.md
nils 3c9a9fc060
ci / docker (backend, backend/Dockerfile, backend) (push) Failing after 13s
ci / docker (frontend, frontend/Dockerfile, frontend) (push) Failing after 12s
Initial commit
2025-12-17 13:37:31 +01:00

1.8 KiB

Bucket CORS for Presigned Asset Fetches

The frontend loads certain assets (e.g. OCR text) with fetch() against their presigned URLs (see frontend/src/preview/DocumentViewerPanel.jsx). Browsers will block that request unless the storage bucket sends CORS headers that allow the frontend origin. Configure a rule that includes:

  • the list of allowed origins (your production, staging, or local domains)
  • GET (and optionally other methods you expose)
  • permissive request headers (usually "*" is fine for presigned URLs)
  • exposed response headers if the frontend needs them (etag, content-length, etc.)

Example CORS document

{
  "CORSRules": [
    {
      "AllowedOrigins": ["https://app.example"],
      "AllowedMethods": ["GET"],
      "AllowedHeaders": ["*"],
      "ExposeHeaders": ["etag", "content-length", "content-type"],
      "MaxAgeSeconds": 300
    }
  ]
}

Replace https://app.example with each domain that must fetch presigned assets. Add additional rules if different origins require different methods.

Applying the rule

AWS S3 CLI

aws s3api put-bucket-cors \
  --bucket <bucket-name> \
  --cors-configuration file://cors.json \
  [--endpoint-url <custom-endpoint>]

Save the JSON payload as cors.json. When targeting S3-compatible providers (e.g. Hetzner, Ceph RGW), pass their endpoint via --endpoint-url.

s3cmd (Ceph RGW / generic S3)

s3cmd setcors cors.json s3://<bucket-name>

MinIO Client (mc)

mc alias set storage <endpoint> <access-key> <secret-key>
mc anonymous set-json storage/<bucket-name> cors.json

Most dashboards expose a similar form—paste the JSON rule into the CORS section for the bucket. Once the rule is active, browsers will allow the frontend to read presigned assets with fetch().