typescriptbeginner

CORS Configuration Middleware

Configure Cross-Origin Resource Sharing with origin allowlists, credentials, and preflight handling.

typescript
import type { IncomingMessage, ServerResponse } from 'http';

interface CorsOptions {
  origins: string[] | '*';
  methods?: string[];
  allowHeaders?: string[];
  exposeHeaders?: string[];
  credentials?: boolean;
  maxAge?: number;
}

function cors(options: CorsOptions) {
  const {
    origins,
    methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
    allowHeaders = ['Content-Type', 'Authorization'],
    exposeHeaders = [],
    credentials = false,
    maxAge = 86400,
  } = options;

  return (req: IncomingMessage, res: ServerResponse, next: () => void) => {
    const origin = req.headers.origin ?? '';

    // Check if origin is allowed
    const allowed = origins === '*' || origins.includes(origin);
    if (!allowed) { next(); return; }

    res.setHeader('Access-Control-Allow-Origin', origins === '*' ? '*' : origin);

    if (credentials) {
      res.setHeader('Access-Control-Allow-Credentials', 'true');
    }

    if (exposeHeaders.length) {
      res.setHeader('Access-Control-Expose-Headers', exposeHeaders.join(', '));
    }

    // Preflight
    if (req.method === 'OPTIONS') {
      res.setHeader('Access-Control-Allow-Methods', methods.join(', '));
      res.setHeader('Access-Control-Allow-Headers', allowHeaders.join(', '));
      res.setHeader('Access-Control-Max-Age', String(maxAge));
      res.writeHead(204);
      res.end();
      return;
    }

    next();
  };
}

// Usage with Express:
// app.use(cors({
//   origins: ['https://myapp.com', 'http://localhost:3000'],
//   credentials: true,
// }));

// Usage with raw http:
// http.createServer((req, res) => {
//   corsMiddleware(req, res, () => { res.end('Hello'); });
// });

export { cors, CorsOptions };

Use Cases

  • API CORS configuration
  • Multi-origin SPA support
  • Secure cross-domain requests

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.