CORS (Cross-Origin Resource Sharing)
CORS or "Cross-Origin Resource Sharing" refers to the situations when a frontend running in a browser has JavaScript code that communicates with a backend, and the backend is in a different "origin" than the frontend.
Same-Domain Deployment
If your project consists of frontend and backend parts, you can deploy both under the same domain to avoid CORS entirely. Here's how:
- Deploy your frontend on
example.com - Deploy your backend API on
example.com/api/* - Configure your Cerces app with
rootPath: "/api"
Now frontend and backend communicate under the same domain. If you still need CORS for development or third-party access, continue reading.
CORS Middleware
Cerces provides built-in middleware for CORS.
import { createCORSMiddleware } from "cerces/cors"
const app = new App({
middleware: [
createCORSMiddleware({
origin: ["http://localhost:8080", "https://example.com"]
}),
]
})Configuration Options
| Name | Type | Description |
|---|---|---|
origin | string | string[] | Function | Allowed origins for CORS requests |
allowMethods | string[] | HTTP methods to allow (defaults to common methods) |
allowHeaders | string[] | Headers that can be included in requests |
maxAge | number | How long browsers can cache preflight responses |
credentials | boolean | Whether to include credentials in CORS requests |
exposeHeaders | string[] | Headers that browsers can access from responses |
How the Middleware Works
The CORS middleware intercepts incoming requests and automatically adds the necessary CORS headers to responses. It handles both simple requests and preflight requests (OPTIONS requests sent by browsers before certain cross-origin requests).
Key Features
- Origin Validation: Checks if the request's origin is allowed based on the
originconfiguration. Supports wildcards (*), specific origins, or custom functions for dynamic validation. - Header Management: Sets
Access-Control-Allow-Origin,Access-Control-Allow-Methods,Access-Control-Allow-Headers, and other headers as needed. - Preflight Handling: Automatically responds to OPTIONS requests with appropriate headers, allowing browsers to proceed with the actual request.
- Credentials Support: When enabled, includes
Access-Control-Allow-Credentialsheader for requests that include cookies or authorization headers. - Caching: Uses
Access-Control-Max-Ageto let browsers cache preflight responses, reducing unnecessary OPTIONS requests.
Handling Preflight Requests
Browsers send preflight OPTIONS requests for complex cross-origin requests (e.g., those with custom headers or methods beyond GET/POST/HEAD). The middleware:
- Detects preflight requests by checking for the
Access-Control-Request-Methodheader. - Validates the requested method against
allowMethods. - Validates requested headers against
allowHeaders. - Returns a 204 No Content response with appropriate CORS headers.
- Allows the browser to proceed with the actual request.
Examples
Allowing All Origins (Development Only)
const app = new App({
middleware: [
createCORSMiddleware({
origin: "*", // Allow any origin - use with caution in production
}),
]
})Dynamic Origin Validation
const app = new App({
middleware: [
createCORSMiddleware({
origin: (origin: string) => {
// Allow localhost in development, specific domains in production
if (origin.includes("localhost")) return origin;
if (origin === "https://myapp.com") return origin;
return null; // Reject
},
credentials: true,
}),
]
})Restrictive Configuration for Production
const app = new App({
middleware: [
createCORSMiddleware({
origin: ["https://myapp.com", "https://admin.myapp.com"],
allowMethods: ["GET", "POST", "PUT", "DELETE"],
allowHeaders: ["Content-Type", "Authorization"],
credentials: true,
maxAge: 86400, // Cache preflight for 24 hours
}),
]
})Exposing Custom Headers
const app = new App({
middleware: [
createCORSMiddleware({
origin: "https://myapp.com",
exposeHeaders: ["X-Custom-Header", "X-Rate-Limit"],
}),
]
})Common Pitfalls
- Wildcard Origin with Credentials: Using
origin: "*"withcredentials: trueis invalid and will cause browser errors. Choose specific origins when credentials are needed. - Missing Vary Header: The middleware automatically adds
Vary: Originwhen origins are restricted, ensuring proper caching behavior. - Preflight Failures: Ensure
allowMethodsandallowHeadersinclude all methods and headers your API uses. Missing ones will cause preflight requests to fail. - Case Sensitivity: HTTP headers are case-insensitive, but ensure consistency in your configuration.
- Browser Caching: Use
maxAgeto control how long browsers cache preflight responses, but be aware that clearing browser cache may be needed during development.
Testing CORS
The middleware includes comprehensive tests covering:
- Origin validation for allowed and disallowed origins
- Preflight request handling
- Header setting for various configurations
- Edge cases like missing origins or invalid requests
To test CORS in your application:
- Use browser developer tools to inspect CORS headers in responses.
- Test with tools like
curlfor simple requests:bashcurl -H "Origin: https://example.com" -v https://your-api.com/endpoint - For preflight testing:bash
curl -X OPTIONS -H "Origin: https://example.com" -H "Access-Control-Request-Method: POST" -v https://your-api.com/endpoint - Verify that credentials work by including cookies or authorization headers in requests.
Remember to test both allowed and disallowed origins to ensure proper security.