CORS Middleware Patterns — Complete Implementation Guide
In this tutorial, you will learn about CORS Middleware Patterns. We cover key concepts, practical examples, and best practices to help you master this topic.
CORS middleware patterns handle cross-origin resource sharing by setting HTTP headers that control which origins, methods, and headers are permitted to access your API from browser-based clients.
What You'll Learn
By the end of this tutorial, you will configure CORS middleware for different scenarios, handle preflight requests, whitelist specific origins, and debug common CORS errors.
Why It Matters
Browsers block cross-origin requests by default. Without CORS middleware, your API cannot be used by web applications hosted on different domains. DodaTech's APIs use CORS middleware to securely allow access from Doda Browser extensions.
Real-World Use
DodaZIP's web interface runs on app.dodazip.com while its API runs on api.dodazip.com. CORS middleware enables the frontend to make API calls across these domains.
CORS Middleware Learning Path
flowchart LR
A[Compression Middleware] --> B[CORS Middleware]
B --> C[Preflight Requests]
C --> D[Origin Whitelisting]
B --> E{You Are Here}
style E fill:#f90,color:#fff
Global CORS Configuration
The cors npm package provides a middleware that sets the necessary CORS headers. The simplest configuration allows all origins, useful for public APIs.
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
app.get("/api/data", (req, res) => {
res.json({ message: "This endpoint is accessible from any origin" });
});
app.listen(3000);
Expected headers in the response:
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Headers: content-type
Origin Whitelisting
For production, restrict access to specific origins. This ensures only your frontend applications can use the API.
const express = require("express");
const cors = require("cors");
const app = express();
const allowedOrigins = [
"https://app.dodazip.com",
"https://admin.dodazip.com",
"http://localhost:3000"
];
app.use(cors({
origin: function (origin, callback) {
if (!origin || allowedOrigins.includes(origin)) {
callback(null, true);
} else {
callback(new Error("Origin not allowed by CORS"));
}
},
methods: ["GET", "POST", "PUT", "DELETE"],
allowedHeaders: ["Content-Type", "Authorization"],
credentials: true,
maxAge: 86400
}));
app.get("/api/user", (req, res) => {
res.json({ user: "Alice" });
});
app.listen(3000);
Expected behavior: Requests from https://app.dodazip.com succeed. Requests from https://evil-site.com receive a CORS error in the browser.
Per-Route CORS Configuration
Different endpoints may need different CORS configurations. Public endpoints allow all origins, while admin endpoints restrict access.
const express = require("express");
const cors = require("cors");
const app = express();
const publicCors = cors({ origin: "*" });
const adminCors = cors({
origin: "https://admin.dodazip.com",
methods: ["GET", "POST"]
});
app.get("/api/posts", publicCors, (req, res) => {
res.json({ posts: [] });
});
app.post("/api/admin/delete", adminCors, (req, res) => {
res.json({ deleted: true });
});
app.listen(3000);
Expected response for POST /api/admin/delete from unauthorized origin:
The browser's CORS mechanism blocks the request, and the Access-Control-Allow-Origin header does not include the requesting origin.
Common Mistakes
Allowing all origins with credentials -- Setting
Access-Control-Allow-Origin: *withcredentials: trueis invalid. You must specify exact origins when using credentials.Not handling preflight requests -- Browsers send OPTIONS requests before actual cross-origin requests. CORS middleware must handle these automatically.
Blocking requests without an Origin header -- Server-to-server requests often lack the Origin header. Allow requests with no origin.
Exposing too many headers -- Only expose headers your frontend needs. Minimize
Access-Control-Expose-Headers.Setting CORS headers on error responses -- Error responses also need CORS headers, or the browser will not display the error to the frontend.
Practice Questions
What is a preflight request? A preflight request (OPTIONS) is sent by the browser before the actual request to check if the server allows the cross-origin request.
Why can't you use
*with credentials? The CORS spec forbids wildcard origins when credentials are included. The server must explicitly list allowed origins.How do you debug CORS issues? Check the browser's network tab for the response headers. Look for
Access-Control-Allow-Originand any CORS error messages.Challenge: Build CORS middleware that logs all CORS violations.
app.use((req, res, next) => {
const origin = req.headers.origin;
if (origin && !allowedOrigins.includes(origin)) {
console.warn(`CORS violation from ${origin} to ${req.url}`);
}
cors({ origin: allowedOrigins })(req, res, next);
});
FAQ
Mini Project
Build a complete CORS middleware configuration with origin whitelisting, per-route policies, error handling, and logging for a multi-domain API.
const express = require("express");
const cors = require("cors");
const app = express();
const origins = {
public: "*",
api: ["https://app.dodazip.com", "https://api.dodazip.com"],
admin: ["https://admin.dodazip.com"]
};
function corsFor(originList, options = {}) {
return cors({
origin: originList,
methods: options.methods || ["GET", "POST", "PUT", "DELETE"],
credentials: originList !== "*",
...options
});
}
app.get("/api/public", corsFor(origins.public), (req, res) => {
res.json({ data: "public" });
});
app.get("/api/protected", corsFor(origins.api, { credentials: true }), (req, res) => {
res.json({ data: "protected" });
});
app.post("/api/admin", corsFor(origins.admin, { methods: ["POST"] }), (req, res) => {
res.json({ data: "admin only" });
});
app.listen(3000);
What's Next
Now that you understand CORS middleware, explore implementing rate limiting as middleware. Then learn about composing multiple middleware functions together.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro