Surfaced during PR #374 review.
When Fastify itself rejects a request before any handler runs (most commonly `FST_ERR_BAD_URL` for malformed percent-encoding like `%g1`, truncated `%E0%`, or invalid UTF-8 sequences), the 400 response carries no `Access-Control-Allow-*` headers. Browser clients then surface the response as a generic CORS / network error instead of the actual status code, which is confusing for debugging and undermines the per-handler CORS work in #371 / #374.
Reproduction
```bash
curl -i -H 'Origin: https://example.com'
'https://melvin.me/melvin/public/git/test-repo.git/info/refs%g1?service=git-upload-pack'
```
```
HTTP/2 400
content-type: application/json
content-length: 155
(no access-control-* headers)
{"error":"Bad Request","code":"FST_ERR_BAD_URL", ...}
```
Scope
This isn't git-specific. The same shape applies to any route — Fastify's URL parser short-circuits before the handler-layer CORS hooks ever run. Possible fixes:
- Global `onError` or `onSend` Fastify hook that decorates 4xx/5xx with the standard CORS headers when the request had an `Origin` header.
- Use `@fastify/cors` plugin (would replace the per-handler CORS blocks across the codebase — bigger refactor but more consistent long-term).
- Custom `schemaErrorFormatter` / `errorHandler` that injects CORS headers on the rejected response.
Refs
Surfaced during PR #374 review.
When Fastify itself rejects a request before any handler runs (most commonly `FST_ERR_BAD_URL` for malformed percent-encoding like `%g1`, truncated `%E0%`, or invalid UTF-8 sequences), the 400 response carries no `Access-Control-Allow-*` headers. Browser clients then surface the response as a generic CORS / network error instead of the actual status code, which is confusing for debugging and undermines the per-handler CORS work in #371 / #374.
Reproduction
```bash
curl -i -H 'Origin: https://example.com'
'https://melvin.me/melvin/public/git/test-repo.git/info/refs%g1?service=git-upload-pack'
```
```
HTTP/2 400
content-type: application/json
content-length: 155
(no access-control-* headers)
{"error":"Bad Request","code":"FST_ERR_BAD_URL", ...}
```
Scope
This isn't git-specific. The same shape applies to any route — Fastify's URL parser short-circuits before the handler-layer CORS hooks ever run. Possible fixes:
Refs
git-protocolheader in CORS preflight responses #371 — `Git-Protocol` allowed in CORS preflight