Skip to content

CORS Middleware Patterns — Complete Implementation Guide

DodaTech Updated 2026-06-28 4 min read

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

  1. Allowing all origins with credentials -- Setting Access-Control-Allow-Origin: * with credentials: true is invalid. You must specify exact origins when using credentials.

  2. Not handling preflight requests -- Browsers send OPTIONS requests before actual cross-origin requests. CORS middleware must handle these automatically.

  3. Blocking requests without an Origin header -- Server-to-server requests often lack the Origin header. Allow requests with no origin.

  4. Exposing too many headers -- Only expose headers your frontend needs. Minimize Access-Control-Expose-Headers.

  5. 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

  1. 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.

  2. Why can't you use * with credentials? The CORS spec forbids wildcard origins when credentials are included. The server must explicitly list allowed origins.

  3. How do you debug CORS issues? Check the browser's network tab for the response headers. Look for Access-Control-Allow-Origin and any CORS error messages.

  4. 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

Does CORS apply to mobile apps?

No. CORS is enforced only by browsers. Mobile apps, server-to-server calls, and tools like curl are not affected by CORS.

What is the difference between CORS and CSP?

CORS controls cross-origin requests from JavaScript. CSP (Content Security Policy) controls what resources the browser loads.

Can I use CORS with WebSockets?

WebSocket connections are not restricted by CORS. However, you should implement origin checking in your WebSocket handshake.

How do I handle CORS for file downloads?

Set the appropriate CORS headers on the download endpoint. The browser must get the correct headers to allow JavaScript to read the response.

What happens if I do not use CORS middleware?

Browser-based frontends on different origins will fail to make requests. Modern single-page applications will break without proper CORS headers.

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