# API CORS Policy

This project uses a centralized CORS filter for API routes under `modules/api/v1/*`.

## Source of truth

- Config: `app/Config/ApiCors.php`
- Filter: `app/Filters/ApiCors.php`
- Filter alias/wiring: `app/Config/Filters.php`

## Allowed origins

- `http://localhost:3000`
- `http://localhost:3002`
- `https://busvalley.net`
- `https://www.busvalley.net`

## Response behavior

For allowed origins, API responses return:

- `Access-Control-Allow-Origin: <request origin>`
- `Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS`
- `Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization`
- `Access-Control-Expose-Headers: Content-Length, Content-Type`
- `Access-Control-Allow-Credentials: true`
- `Vary: Origin`

`OPTIONS` preflight requests are handled early and return `204`.

## Why this avoids intermittent CORS failures

- Headers are emitted in both filter `before` and `after`, so success and framework error responses are consistently covered.
- Preflight is short-circuited quickly, reducing request chain variance/timeouts.
- `Vary: Origin` prevents shared caches/proxies from reusing a mismatched origin response.
- Origin is explicit and never wildcard, which is required when credentials are allowed.

## Server config note

CORS headers should be managed by PHP filter only.

- Keep `.htaccess`/Apache/LiteSpeed CORS header injection disabled for this API.
- If server adds CORS headers too, remove those directives to avoid duplicates/conflicts.

## Verification

Use:

```bash
bash scripts/verify-cors.sh
```

Or pass custom API base + endpoint:

```bash
bash scripts/verify-cors.sh "https://data.busvalley.com/busvalley_new/modules/api/v1" "/locations"
```

