feat(19.3-03): storage.uploads.public_url for direct bucket or CDN file URLs

- OpenBucket validates public_url (absolute http/https, host, no user info, query
  or fragment; the error names the key) and records it next to public_path_prefix
- a set public_url logs one start-up line: the bucket behind it must hold only
  public files, since it bypasses the is_public check
- attach.PublicURLBase; PublicURL, File.URL and thumbnail URLs use the base when
  set and keep the public_path_prefix proxy URLs otherwise
- TestPublicURLSmoke; storage Public URL base section, attachments, configuration
  and lagoon README
This commit is contained in:
Jakub Zych
2026-10-15 18:13:00 +02:00
parent 2e22e9f9a6
commit 2e87efae54
7 changed files with 127 additions and 9 deletions

View File

@@ -79,6 +79,22 @@ Credentials come from the standard AWS environment: `AWS_ACCESS_KEY_ID` and `AWS
The [Serving files](#serving-files) route reads through the bucket, so it serves an S3 bucket exactly as it serves a directory.
## Public URL base
By default every file and thumbnail URL starts with `public_path_prefix`, a path on the application's own host. When a public bucket or a CDN serves the files directly, set `storage.uploads.public_url` (environment `SUMMER_STORAGE__UPLOADS__PUBLIC_URL`) to its base URL:
```yaml
uploads:
bucket_url: s3://acme-uploads?region=eu-central-1
public_url: https://cdn.example.com/uploads
```
`attach.PublicURL`, `attach.File.URL` and thumbnail URLs then are that base, one slash and the blob key, which keeps the partition layout: `https://cdn.example.com/uploads/5f1/d0c/2e9/5f1d0c2e9a7b4c3d8e6f.jpg`. `attach.PublicURLBase` returns the base. The value must be an absolute `http` or `https` URL with a host and without user info, query or fragment; anything else stops the start-up with an error naming the key. Thumbnails are written to the bucket when they are first requested through `attach.File.Thumb`, so their URLs work behind the base as well.
The base applies to every URL the framework builds, private files included. The `/storage/uploads` route checks `is_public` before it serves a file; a public bucket or a CDN serves any key it holds. Use `public_url` only for a bucket that holds public files alone, or knowingly rely on the 22 random hexadecimal characters of each disk name. `serve` logs one line at start-up naming the host and this rule.
Leave `public_url` unset to keep the URLs under `public_path_prefix`. With `storage.uploads.serve` on, those URLs go through the [Serving files](#serving-files) route, which works for an S3 bucket too, and private files stay protected.
## Serving files
The framework mounts no file route unless you ask for one. Set `storage.uploads.serve` to `true` (environment `SUMMER_STORAGE__UPLOADS__SERVE=true`, default `false`) and the router registers `GET <public_path_prefix>/{path...}` on `attach.StaticHandlerPublic`: