CORS Middleware ​
cors() brings fine-grained CORS control to bunway while keeping everything Bun-native. The middleware examines the incoming Origin/Access-Control headers, decides whether to allow the request, and sets the appropriate response headers.
Coming from Express?
This works just like the cors npm package. Same options, same patterns.
Basic usage ​
import { cors } from "bunway";
app.use(cors()); // wildcard
app.use(cors({ origin: true })); // reflect request origin
app.use(cors({ origin: "https://app.example.com" }));Set credentials: true to allow cookies/authorization headers—bunway automatically prevents * when credentials are enabled by reflecting the incoming origin instead.
app.use(cors({ origin: true, credentials: true }));Credentials
When credentials: true, bunway automatically reflects the request origin instead of using *. Ensure your allow list covers every origin that should receive credentialed responses.
Allow list patterns ​
string– match exact originRegExp– pattern match(origin, req) => string | false– custom logic (return the origin to allow,falseto block)- Arrays combine multiple strings/regexes
app.use(
cors({
origin: (origin, req) => {
// Custom logic with access to the request
if (origin?.startsWith("http://localhost")) return origin;
if (req.get("X-Internal-Request")) return origin;
return false;
},
})
);Preflight requests ​
Preflight (OPTIONS) requests are answered automatically with:
Access-Control-Allow-OriginAccess-Control-Allow-Methods(customizable viamethodsoption)Access-Control-Allow-Headers(explicit list or echo request header)Access-Control-Allow-Credentialswhencredentials: trueAccess-Control-Max-Age(default 600 seconds)
The middleware also ensures the proper Vary header is set to keep caches honest.
Header merging ​
CORS headers are set directly on the response. bunway's router finalizer preserves these headers even if your handler returns a native Response object:
app.get("/raw", () => new Response("raw", { status: 202 }));
// CORS headers still applied!Options reference ​
CORS Options reference
origin:"*"|true|string|RegExp|(string | RegExp)[]|(origin, req) => string | false- Decide which origins are allowed. Returning
falseblocks the request; whencredentials: true, bunWay reflects the approved origin instead of"*".
- Decide which origins are allowed. Returning
credentials:boolean(defaultfalse)- Allow credentialed requests. bunWay automatically prevents
"*"when enabled.
- Allow credentialed requests. bunWay automatically prevents
methods:string[](default['GET','HEAD','PUT','PATCH','POST','DELETE','OPTIONS'])- Whitelist methods used in preflight responses.
allowedHeaders:string[]- Force a specific allow-list instead of echoing
Access-Control-Request-Headers.
- Force a specific allow-list instead of echoing
exposedHeaders:string[]- Populate
Access-Control-Expose-Headers.
- Populate
maxAge:number(default600)- Cache duration (seconds) for successful preflight responses.
preflightContinue:boolean(defaultfalse)- Pass preflight requests to the next handler instead of responding immediately.
Recommendations ​
- Reflect (
origin: true) when you need credentials. - Keep the allow-list tight in production—prefer regex/string arrays over wildcards.
Production allow list
Audit CORS settings regularly. Accidentally allowing * with credentials or forgetting to restrict origins can expose sensitive endpoints.
- Combine with
errorHandler()to log disallowed origins or unexpected headers.
For type details see CorsOptions in the API Reference.