Object Store CORS / TempURL test
This page is served from Origin: — put exactly this value in
X-Container-Meta-Access-Control-Allow-Origin of the test container.
Separate multiple origins with spaces (e.g. https://a.example https://b.example);
Swift splits this header on spaces — a comma-separated list is treated as a single value
and CORS then fails silently.
1. Generate a TempURL (optional, in the browser)
Base URL (Swift endpoint)
HMAC path style
/v1/AUTH_<project-id>/<container>/<object> (Keystone convention)
/<container>/<object> (bare path)
Container/object path (relative to the endpoint)
Temp-URL-Key (X-Account- or X-Container-Meta-Temp-URL-Key)
HTTP method PUT GET
Digest SHA-256 (64 hex) SHA-1 (40 hex)
Valid for (seconds)
Generate TempURL
TempURL
The HMAC string is <METHOD>\n<expires>\n<path>
(the host is never part of the HMAC). The path must be either
/v1/AUTH_<project-id>/<container>/<object> or the bare
/<container>/<object> — both are accepted; anything else, e.g.
/v1/<project-id>/... without AUTH_, returns 401.
Only the query parameter temp_url_sig is accepted — tempurl_sig
(without underscores) returns 401. temp_url_method is optional (the method must be
part of the HMAC and must match the request). Both SHA-256 and SHA-1 signatures are valid.
Note: crypto.subtle is only available in a secure context — the TempURL generator
above therefore only works from https://cors-test.f3r.nl, not from
http://85.10.185.174.
2. Browser tests (cross-origin, from this page)
PUT via TempURL (triggers preflight)
GET via plain object URL
PUT followed by GET
On a CORS error the browser shows TypeError: Failed to fetch.
Visible response headers require X-Container-Meta-Access-Control-Expose-Headers.
The plain GET button only works if the container is publicly readable
(X-Container-Read: .r:*); otherwise the store returns 401 — visible in the log
rather than a CORS error, because 401 responses also carry
Access-Control-Allow-Origin for allowed origins.
Verified 2026-11-13: an OPTIONS preflight for a TempURL PUT returns 200 +
Access-Control-Allow-Origin + Access-Control-Allow-Methods + max-age,
and the PUT response (201) also contains Access-Control-Allow-Origin — browser
fetches therefore work end-to-end. A PUT can afterwards be confirmed with a GET/HEAD.
For the S3 endpoint (s3.objectstore.eu): presigned GETs work browser-side (200 + ACAO, a
simple GET needs no preflight); presigned PUTs fail on the preflight (OPTIONS → 405) —
cross-origin uploads are therefore NOT possible via S3; use TempURL (Swift endpoint) or
formpost instead.
Log