CORS
Add cross-origin resource sharing headers to your API responses.
When your API runs on one domain (like api.example.com) and your frontend on another (like app.example.com), browsers block the requests by default. CORS headers tell the browser it's safe to proceed.
Katman provides corsHeaders() — a function that returns the right headers for your configuration.
Basic usage
import { } from "katman/cors"
const = ({
: "https://app.example.com",
: true,
})This returns a plain object:
{
"access-control-allow-origin": "https://app.example.com",
"access-control-allow-credentials": "true",
"access-control-allow-methods": "GET, POST, PUT, PATCH, DELETE, OPTIONS",
"access-control-allow-headers": "Content-Type, Authorization"
}You can merge these headers into your responses however your server setup requires.
Allow all origins
The default (no origin option or origin: "*") allows any origin:
import { } from "katman/cors"
const = ()
// "access-control-allow-origin": "*"Using origin: "*" with credentials: true doesn't work — browsers reject it. If you need credentials, specify the exact origin.
Multiple origins
Pass an array to allow several specific origins:
import { } from "katman/cors"
const = ({
: [
"https://app.example.com",
"https://admin.example.com",
],
}, requestOrigin)The second argument is the requesting origin (from the Origin header on the incoming request). Katman checks if it's in the list and responds with the matching origin. A Vary: Origin header is automatically included so caches work correctly.
Dynamic origin matching
For more complex rules, pass a function:
import { } from "katman/cors"
const = ({
: () => {
return .(".example.com")
},
}, req.headers.get("origin"))The function receives the requesting origin and returns true to allow it or false to block it. Like array origins, Vary: Origin is added automatically.
All options
| Option | Type | Default | Description |
|---|---|---|---|
origin | string | string[] | (origin) => boolean | "*" | Which origins are allowed |
methods | string[] | ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"] | Allowed HTTP methods |
allowedHeaders | string[] | ["Content-Type", "Authorization"] | Headers the client can send |
exposedHeaders | string[] | none | Response headers the client can read |
credentials | boolean | false | Allow cookies and auth headers |
maxAge | number | none | Preflight cache duration in seconds |
Example with handler()
If you're using handler() with a custom server, you can wrap it to add CORS headers:
import { } from "katman/cors"
const = k.handler(appRouter)
const = ({ : "https://app.example.com", : true })
async function (: Request): <Response> {
// Handle preflight
if (. === "OPTIONS") {
return new (null, { : 204, : })
}
const = await ()
// Add CORS headers to the response
const = new (.headers)
for (const [, ] of .()) {
.(, )
}
return new (.body, {
: .status,
,
})
}