Existing documentation URL(s)
What changes are you suggesting?
The page states that AllowedOrigins entries must be a valid Origin header
value (scheme://host[:port]) and that "Origin values must match exactly".
It does not mention wildcards.
In practice, the R2 S3-compatible API (PutBucketCors) accepts partial
wildcards in AllowedOrigins and matches them at request time. This is easy to
rely on by accident, and equally easy to have quietly break, because nothing in
the docs says whether it is supported.
Tested against a real bucket via PutBucketCors / GetBucketCors:
AllowedOrigin value |
Result |
https://*-myapp.<subdomain>.workers.dev |
Accepted, and matches as expected |
https://*.<subdomain>.workers.dev |
Accepted |
http://localhost |
Accepted (exact origin, port 80) |
http://localhost:* |
Rejected — 400 MalformedXML |
For the first entry, the matching behaves correctly rather than degrading into
"allow all". With only that wildcard added:
https://a1b2c3d4-myapp.<subdomain>.workers.dev → receives
Access-Control-Allow-Origin
https://other-worker.<subdomain>.workers.dev → no CORS header
https://myapp.<subdomain>.workers.dev.example.com (fake suffix) → no CORS header
So the feature appears to work deliberately, not incidentally.
The request is to make the docs and the API agree, in whichever direction is
correct:
- If partial wildcards are supported, document the syntax: which positions
a * may appear in, whether it may span dots, and that a port wildcard
(http://localhost:*) is not accepted.
- If they are not supported, say so explicitly, and ideally have
PutBucketCors reject them the way it rejects http://localhost:*.
Accepting a value and matching it, while documenting exact-match-only, is the
worst of both: users build on it without knowing it is unsupported.
Either way, please state the port case directly. Allowing a local dev server on
an arbitrary port is a very common need, and today the only way to find out that
http://localhost:* is impossible is to try it and read a MalformedXML
response, which does not suggest the actual cause.
Additional information
The behaviour was found while debugging a browser upload that worked from one
deployment and failed from another with Failed to fetch; the cause was the
second origin missing from the bucket's CORS policy.
One note that may be worth a line in the page regardless of the wildcard
question: responses served from the *.r2.dev public URL are cached at the
edge, so immediately after changing a CORS policy, GETs can still return the
previously cached response without the Access-Control-Allow-Origin header.
This makes a correct change look like it partially failed. Adding a cache-busting
query parameter shows the new policy right away.
Existing documentation URL(s)
What changes are you suggesting?
The page states that
AllowedOriginsentries must be a validOriginheadervalue (
scheme://host[:port]) and that "Origin values must match exactly".It does not mention wildcards.
In practice, the R2 S3-compatible API (
PutBucketCors) accepts partialwildcards in
AllowedOriginsand matches them at request time. This is easy torely on by accident, and equally easy to have quietly break, because nothing in
the docs says whether it is supported.
Tested against a real bucket via
PutBucketCors/GetBucketCors:AllowedOriginvaluehttps://*-myapp.<subdomain>.workers.devhttps://*.<subdomain>.workers.devhttp://localhosthttp://localhost:*400 MalformedXMLFor the first entry, the matching behaves correctly rather than degrading into
"allow all". With only that wildcard added:
https://a1b2c3d4-myapp.<subdomain>.workers.dev→ receivesAccess-Control-Allow-Originhttps://other-worker.<subdomain>.workers.dev→ no CORS headerhttps://myapp.<subdomain>.workers.dev.example.com(fake suffix) → no CORS headerSo the feature appears to work deliberately, not incidentally.
The request is to make the docs and the API agree, in whichever direction is
correct:
a
*may appear in, whether it may span dots, and that a port wildcard(
http://localhost:*) is not accepted.PutBucketCorsreject them the way it rejectshttp://localhost:*.Accepting a value and matching it, while documenting exact-match-only, is the
worst of both: users build on it without knowing it is unsupported.
Either way, please state the port case directly. Allowing a local dev server on
an arbitrary port is a very common need, and today the only way to find out that
http://localhost:*is impossible is to try it and read aMalformedXMLresponse, which does not suggest the actual cause.
Additional information
The behaviour was found while debugging a browser upload that worked from one
deployment and failed from another with
Failed to fetch; the cause was thesecond origin missing from the bucket's CORS policy.
One note that may be worth a line in the page regardless of the wildcard
question: responses served from the
*.r2.devpublic URL are cached at theedge, so immediately after changing a CORS policy,
GETs can still return thepreviously cached response without the
Access-Control-Allow-Originheader.This makes a correct change look like it partially failed. Adding a cache-busting
query parameter shows the new policy right away.