cors-middleware
The cors middleware handles Cross-Origin Resource Sharing (CORS) by setting the appropriate response headers. This is required when your API is accessed from a different domain than the one serving it.
Installation
The CORS middleware is included with Remix. No additional installation is needed.
Import
import { cors } from 'remix/cors-middleware'API
cors(options?)
Returns a middleware function that sets CORS headers on responses and handles preflight requests.
let router = createRouter({
middleware: [
cors({
origin: 'https://myapp.com',
}),
],
})Options
| Option | Type | Default | Description |
|---|---|---|---|
origin | string | string[] | boolean | (origin: string) => string | false | false | Configures the Access-Control-Allow-Origin header. See Origin Configuration below. |
methods | string[] | ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'] | Allowed HTTP methods. Sets the Access-Control-Allow-Methods header. |
allowedHeaders | string[] | Reflects request headers | Headers the client is allowed to send. Sets the Access-Control-Allow-Headers header. |
exposedHeaders | string[] | [] | Headers the client is allowed to read from the response. Sets the Access-Control-Expose-Headers header. |
credentials | boolean | false | Whether to include the Access-Control-Allow-Credentials: true header. Required for cookies and HTTP authentication. |
maxAge | number | undefined | How long (in seconds) the browser should cache the preflight response. Sets the Access-Control-Max-Age header. |
Origin Configuration
The origin option supports several formats:
Boolean
true--- Reflects the request'sOriginheader (allows any origin).false--- Disables CORS headers entirely.
String
A single allowed origin:
cors({ origin: 'https://myapp.com' })Use '*' to allow all origins (cannot be combined with credentials: true).
Array
Multiple allowed origins:
cors({ origin: ['https://myapp.com', 'https://admin.myapp.com'] })Function
A function that receives the request's Origin header and returns an allowed origin string, or false to deny:
cors({
origin(requestOrigin) {
if (requestOrigin?.endsWith('.myapp.com')) {
return requestOrigin
}
return false
},
})Preflight Handling
When a browser sends a preflight request (an OPTIONS request with Access-Control-Request-Method), the middleware:
- Responds with the configured CORS headers.
- Returns a
204 No Contentresponse immediately, without calling downstream middleware or the route handler.
This means preflight requests are fast and do not hit your application logic.
Examples
Allow All Origins (Public API)
cors({
origin: '*',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type'],
})Specific Origins with Credentials
cors({
origin: ['https://myapp.com', 'https://admin.myapp.com'],
credentials: true,
maxAge: 86400,
})Never use origin: '*' with credentials
Setting origin: '*' with credentials: true is not allowed by browsers and will cause requests to fail. If you need cookies or HTTP authentication, specify exact origins.
Dynamic Origins
For multi-tenant applications or many subdomains:
cors({
origin(requestOrigin) {
// Look up allowed origins from a database or config
let allowedOrigins = getAllowedOrigins()
if (requestOrigin && allowedOrigins.includes(requestOrigin)) {
return requestOrigin
}
return false
},
credentials: true,
})Expose Custom Headers
Allow the client to read custom response headers:
cors({
origin: 'https://myapp.com',
exposedHeaders: ['X-Total-Count', 'X-Request-Id'],
})Related
- Middleware --- How middleware works in Remix.
- Security Guide --- CORS in the context of application security.
- cop-middleware --- Cross-origin protection using browser security headers.