fix(api-client): Treat * as wildcard in preflight Access-Control-Allow-Headers (#12503)
## fix(api-client): treat `*` as wildcard in preflight
`Access-Control-Allow-Headers` check
### Background
We run a self-hosted Turborepo remote cache backed by an AWS Lambda
Function URL with `TURBO_PREFLIGHT=true`. Our CORS configuration uses
`Access-Control-Allow-Headers: *`. I'm thinking this is likely what most
self-hosted remote cache deployments use too, which is why I am
proposing handling this in turborepo core too. I appreciate that a fix
is to be explicit with CORS headers, like `allow_headers =
["Authorization", "Content-Type", "User-Agent", "x-artifact-duration",
"x-artifact-tag", "x-artifact-sha", "x-artifact-dirty-hash" ]` etc.
although some may not have control and I thought that `*` is quite a
common value.
### The problem
With `TURBO_PREFLIGHT=true`, every artifact request returns 401 despite
the token being valid. Without preflight, the same token works fine. We
traced it to `do_preflight` in `turborepo-api-client`. After the OPTIONS
preflight, turbo checks `Access-Control-Allow-Headers` to decide whether
to include the `Authorization` header:
```rust
let allow_auth = AUTHORIZATION_REGEX.is_match(allowed_headers);
```
The regex `(?i)(?:^|,) *authorization *(?:,|$)` looks for the literal
string `authorization` in a comma-separated list. The CORS wildcard `*`
— which per the Fetch spec means "all headers are allowed" — doesn't
match. So `allow_auth` is `false`, turbo strips the Bearer token, and
the server returns 401. So anyone configuring CORS with `*` would run
into this too.
### The fix
Short-circuit with `allowed_headers == "*"` before the regex, matching
the CORS spec where `*` means "allow all headers". A test case is added
alongside the existing `allow-auth` and `no-allow-auth` tests.
Let me know if you have any questions. Rust isn't my strongest language
so this PR was helped along with Opus 🫶
---------
Co-authored-by: Anthony Shew <anthonyshew@gmail.com>