Access-Control-Allow-Origin: * allows any website to access your resources. Always specify exact origins in production.
The cors npm package is the standard solution for Express.js CORS handling. It's well-maintained, handles all edge cases, and is used by millions of projects (issue #138).
npm install cors
const express = require('express');
const cors = require('cors');
const app = express();
// Allow specific origin
app.use(cors({
origin: 'https://example.com',
credentials: true
}));
app.get('/api/data', function(req, res) {
res.json({message: 'CORS enabled'});
});
app.listen(3000);
To allow multiple specific origins (issue #146):
const express = require('express');
const cors = require('cors');
const app = express();
const allowedOrigins = ['https://example.com', 'https://app.example.com'];
app.use(cors({
origin: function (origin, callback) {
// Allow requests with no origin (mobile apps, curl, etc)
if (!origin) return callback(null, true);
if (allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
credentials: true,
optionsSuccessStatus: 204
}));
app.get('/api/data', function(req, res) {
res.json({message: 'CORS enabled'});
});
app.listen(3000);
const express = require('express');
const cors = require('cors');
const app = express();
// Public endpoint - open CORS
app.get('/api/public', cors(), function(req, res) {
res.json({message: 'Public endpoint'});
});
// Private endpoint - restricted CORS
const corsOptions = {
origin: 'https://example.com',
credentials: true
};
app.get('/api/private', cors(corsOptions), function(req, res) {
res.json({message: 'Private endpoint'});
});
app.listen(3000);
If you prefer not to use a package, implement CORS manually with proper origin validation:
const express = require('express');
const app = express();
// List of allowed origins
const allowedOrigins = [
'https://example.com',
'https://app.example.com'
];
// CORS middleware
app.use(function(req, res, next) {
const origin = req.headers.origin;
// Validate origin
if (allowedOrigins.includes(origin)) {
res.header("Access-Control-Allow-Origin", origin);
res.header("Vary", "Origin");
res.header("Access-Control-Allow-Credentials", "true");
}
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
// Handle preflight
if (req.method === 'OPTIONS') {
res.header("Access-Control-Max-Age", "86400");
return res.sendStatus(204);
}
next();
});
// Your routes
app.get('/api/data', function(req, res) {
res.json({message: 'CORS enabled'});
});
app.post('/api/data', function(req, res) {
res.json({message: 'POST request'});
});
app.listen(3000, function() {
console.log('Server running on port 3000');
});
Create a reusable middleware module:
// cors-middleware.js
function corsMiddleware(options = {}) {
const {
origins = [],
credentials = true,
methods = ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
headers = ['Content-Type', 'Authorization', 'X-Requested-With'],
maxAge = 86400
} = options;
return function(req, res, next) {
const origin = req.headers.origin;
// Validate origin
if (origins.includes(origin)) {
res.header("Access-Control-Allow-Origin", origin);
res.header("Vary", "Origin");
if (credentials) {
res.header("Access-Control-Allow-Credentials", "true");
}
}
res.header("Access-Control-Allow-Methods", methods.join(", "));
res.header("Access-Control-Allow-Headers", headers.join(", "));
// Handle preflight
if (req.method === 'OPTIONS') {
res.header("Access-Control-Max-Age", maxAge.toString());
return res.sendStatus(204);
}
next();
};
}
module.exports = corsMiddleware;
// Usage in app.js
const express = require('express');
const corsMiddleware = require('./cors-middleware');
const app = express();
app.use(corsMiddleware({
origins: ['https://example.com', 'https://app.example.com'],
credentials: true
}));
app.get('/api/data', (req, res) => {
res.json({message: 'CORS enabled'});
});
app.listen(3000);
Note: The cors package handles preflight requests automatically, validates origins correctly, and handles edge cases you might miss in manual implementations. See the official cors package documentation for more information.
For comprehensive testing instructions including curl commands, browser DevTools usage, and troubleshooting common CORS errors, see the CORS Testing Guide.
The content on this site stays fresh thanks to help from users like you! If you have suggestions or would like to contribute, fork us on GitHub.
Save 39% on CORS in Action with promotional code hossainco at manning.com/hossain