CORS
Cross-Origin Resource Sharing configuration. Handles preflight OPTIONS requests and sets CORS headers on responses.
The cors() function returns an object with two pieces:
preflight(route)registers a catch-allOPTIONS /**route that responds to preflight requests with the appropriate CORS headers.headers(request, response)adds CORS headers to a response. Call it inonResponse.
import { setup, route, cors } from "@hectoday/http";
const corsConfig = cors({ origin: "*" });
const app = setup({
onResponse: ({ request, response }) => {
return corsConfig.headers(request, response);
},
routes: [
corsConfig.preflight(route),
/* ... */
],
}); cors() options
cors({
origin: "*", // or string[]
methods: ["GET", "POST", "PUT", "DELETE"], // Allowed methods
allowHeaders: ["Content-Type", "Authorization"], // Allowed request headers
exposeHeaders: ["X-Request-Id"], // Headers the browser can read
credentials: true, // Allow cookies/auth headers
maxAge: 86400, // Preflight cache duration (seconds)
}); origin
Type: string | string[]
Which origins are allowed to make requests.
// Allow all origins
cors({ origin: "*" });
// Allow one origin
cors({ origin: "https://myapp.com" });
// Allow multiple origins
cors({ origin: ["https://myapp.com", "https://admin.myapp.com"] }); methods
Type: string[] — Default: ["GET", "HEAD", "PUT", "PATCH", "POST", "DELETE"]
HTTP methods allowed in cross-origin requests.
allowHeaders
Type: string[] — Default: []
Request headers the client is allowed to send. If not specified, the handler echoes back whatever the browser requests in Access-Control-Request-Headers.
exposeHeaders
Type: string[] — Default: []
Response headers the browser is allowed to read. By default, browsers can only read a small set of “simple” headers. Add custom headers here.
cors({ origin: "*", exposeHeaders: ["X-Request-Id", "X-Response-Time"] }); credentials
Type: boolean — Default: false
Whether to allow credentials (cookies, Authorization header) in cross-origin requests. When true, origin cannot be "*". The handler will echo back the requesting origin instead and set Access-Control-Allow-Credentials: true.
maxAge
Type: number — Default: none
How long (in seconds) the browser caches the preflight response. A preflight is an OPTIONS request the browser sends before the actual request. Caching it avoids an extra round trip.
How it works
Preflight requests
corsConfig.preflight(route) registers a catch-all OPTIONS /** route. When the browser sends a preflight request, this route responds with a 204 No Content and the appropriate CORS headers (Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, etc.). The request never reaches your other routes.
Actual requests
corsConfig.headers(request, response) reads the Origin header from the request, checks it against the allowed origins, and returns a new response with the CORS headers attached. Call it at the end of onResponse and return its result.
Example: API with frontend
import { setup, route, cors } from "@hectoday/http";
const corsConfig = cors({
origin: ["https://myapp.com", "http://localhost:5173"],
credentials: true,
exposeHeaders: ["X-Request-Id"],
});
const app = setup({
onResponse: ({ request, response }) => {
return corsConfig.headers(request, response);
},
routes: [
corsConfig.preflight(route),
/* ... */
],
}); This allows requests from the production frontend (myapp.com) and the local dev server (localhost:5173), with cookies and auth headers permitted.