Meteor is a full-stack JavaScript framework built on Node.js. To add CORS authorization to a Meteor application, use the webapp package's WebApp.rawConnectHandlers to customize HTTP headers.
Access-Control-Allow-Origin: * allows any website to access your resources. Always specify exact origins in production.
Meteor uses two different communication protocols:
The WebApp.rawConnectHandlers middleware affects HTTP requests but not DDP connections. If you're exposing REST APIs alongside your Meteor application, you'll need proper CORS configuration.
Here's a production-ready CORS implementation with origin validation, preflight handling, and proper security headers:
// server/cors.js
import { WebApp } from 'meteor/webapp';
const allowedOrigins = [
'https://example.com',
'https://app.example.com',
'https://admin.example.com'
];
WebApp.rawConnectHandlers.use(function(req, res, next) {
const origin = req.headers.origin;
// Validate origin against whitelist
if (allowedOrigins.includes(origin)) {
res.setHeader("Access-Control-Allow-Origin", origin);
res.setHeader("Vary", "Origin");
res.setHeader("Access-Control-Allow-Credentials", "true");
}
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Requested-With");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
// Handle preflight requests
if (req.method === "OPTIONS") {
res.setHeader("Access-Control-Max-Age", "86400"); // 24 hours
res.writeHead(204);
res.end();
return;
}
next();
});
You can configure different CORS policies for different API paths using the optional path argument:
// Public API - allows any origin
WebApp.rawConnectHandlers.use("/api/public", function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
if (req.method === "OPTIONS") {
res.setHeader("Access-Control-Max-Age", "86400");
res.writeHead(204);
res.end();
return;
}
return next();
});
// Private API - restricted to specific origins
const allowedOrigins = [
'https://example.com',
'https://app.example.com'
];
WebApp.rawConnectHandlers.use("/api/private", function(req, res, next) {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader("Access-Control-Allow-Origin", origin);
res.setHeader("Access-Control-Allow-Credentials", "true");
res.setHeader("Vary", "Origin");
}
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
if (req.method === "OPTIONS") {
res.setHeader("Access-Control-Max-Age", "86400");
res.writeHead(204);
res.end();
return;
}
next();
});
For better security and flexibility, load allowed origins from your Meteor settings:
settings.json:
{
"cors": {
"origins": [
"https://example.com",
"https://app.example.com"
]
}
}
server/cors.js:
import { Meteor } from 'meteor/meteor';
import { WebApp } from 'meteor/webapp';
if (Meteor.isServer) {
const allowedOrigins = Meteor.settings.cors?.origins || [];
WebApp.rawConnectHandlers.use(function(req, res, next) {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader("Access-Control-Allow-Origin", origin);
res.setHeader("Vary", "Origin");
}
if (req.method === "OPTIONS") {
res.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
res.setHeader("Access-Control-Max-Age", "86400");
res.writeHead(204);
res.end();
return;
}
next();
});
}
Run Meteor with settings:
meteor --settings settings.json
For more advanced use cases, consider using community packages:
meteor add simple:rest
When making authenticated requests to Meteor APIs, clients typically send:
application/json
Your server must allow these headers with Access-Control-Allow-Headers. The examples above include these by default.
Access-Control-Allow-Origin: * cannot be used with Access-Control-Allow-Credentials: trueVary: Origin is required when dynamically setting Access-Control-Allow-Origin to prevent caching issuesFor 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