cors vs @fastify/cors vs @koa/cors vs koa-cors
CORS Middleware for Node.js Comparison
1 Year
cors@fastify/cors@koa/corskoa-corsSimilar Packages:
What's CORS Middleware for Node.js?

CORS (Cross-Origin Resource Sharing) middleware for Node.js is essential for enabling or restricting resources on a web server to be requested from another domain outside the domain from which the first resource was served. This is a security feature implemented by web browsers to prevent malicious sites from making requests to a different domain without permission. CORS middleware allows developers to configure their servers to specify which origins are allowed to access resources, what HTTP methods are permitted, and whether credentials (like cookies) can be included in cross-origin requests. This is particularly important for APIs that are accessed by web applications hosted on different domains. The middleware handles the CORS preflight requests (OPTIONS method) and adds the appropriate headers to the responses to inform the browser about the server's CORS policy. This ensures that the web application can interact with the server securely and as intended.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
cors19,707,8566,145-317 years agoMIT
@fastify/cors1,120,775460115 kB34 months agoMIT
@koa/cors766,30974113.2 kB212 years agoMIT
koa-cors16,954244-1310 years agoMIT
Feature Comparison: cors vs @fastify/cors vs @koa/cors vs koa-cors

Framework Compatibility

  • cors:

    cors is framework-agnostic but is most commonly used with Express.js. It can be integrated into any Node.js server application.

  • @fastify/cors:

    @fastify/cors is specifically designed for the Fastify framework, leveraging its plugin architecture for optimal performance and integration.

  • @koa/cors:

    @koa/cors is built for the Koa framework, providing a middleware solution that aligns with Koa's async/await style.

  • koa-cors:

    koa-cors is tailored for Koa but is designed for older versions (Koa 1.x). It is less flexible and maintained compared to @koa/cors.

Performance

  • cors:

    cors is efficient for most applications, but its performance can vary depending on how it is configured and used within the Express.js middleware stack.

  • @fastify/cors:

    @fastify/cors is optimized for performance, making it one of the fastest CORS middleware available, which is crucial for high-performance applications.

  • @koa/cors:

    @koa/cors offers good performance for Koa applications, but it may not be as fast as @fastify/cors due to the overhead of middleware execution in Koa.

  • koa-cors:

    koa-cors is lightweight and introduces minimal overhead, but it lacks the optimizations found in more modern CORS middleware.

Configuration Flexibility

  • cors:

    cors is highly configurable, supporting a wide range of options such as allowed origins, methods, headers, and credentials, making it suitable for complex CORS scenarios.

  • @fastify/cors:

    @fastify/cors provides flexible configuration options, allowing developers to set allowed origins, methods, headers, and more, all while maintaining a simple API.

  • @koa/cors:

    @koa/cors allows for configurable CORS settings, including support for dynamic origin functions, making it versatile for various use cases.

  • koa-cors:

    koa-cors offers basic configuration options but is limited compared to the more feature-rich @koa/cors and cors packages.

Ease of Use: Code Examples

  • cors:

    Express CORS Example

    const express = require('express');
    const cors = require('cors');
    
    const app = express();
    app.use(cors({
      origin: 'https://example.com', // Allow only this origin
      methods: ['GET', 'POST'], // Allow only these methods
    }));
    
    app.get('/', (req, res) => {
      res.send('CORS enabled for example.com');
    });
    
    app.listen(3000, () => {
      console.log('Server running on http://localhost:3000');
    });
    
  • @fastify/cors:

    Fastify CORS Example

    const fastify = require('fastify')();
    const cors = require('@fastify/cors');
    
    fastify.register(cors, {
      origin: 'https://example.com', // Allow only this origin
      methods: ['GET', 'POST'], // Allow only these methods
    });
    
    fastify.get('/', (req, reply) => {
      reply.send('CORS enabled for example.com');
    });
    
    fastify.listen(3000, () => {
      console.log('Server running on http://localhost:3000');
    });
    
  • @koa/cors:

    Koa CORS Example

    const Koa = require('koa');
    const cors = require('@koa/cors');
    
    const app = new Koa();
    app.use(cors({
      origin: 'https://example.com', // Allow only this origin
      allowMethods: 'GET, POST', // Allow only these methods
    }));
    
    app.use(ctx => {
      ctx.body = 'CORS enabled for example.com';
    });
    
    app.listen(3000, () => {
      console.log('Server running on http://localhost:3000');
    });
    
  • koa-cors:

    Koa CORS Example (Old)

    const Koa = require('koa');
    const cors = require('koa-cors');
    
    const app = new Koa();
    app.use(cors({
      origin: 'https://example.com', // Allow only this origin
      methods: 'GET, POST', // Allow only these methods
    }));
    
    app.use(ctx => {
      ctx.body = 'CORS enabled for example.com';
    });
    
    app.listen(3000, () => {
      console.log('Server running on http://localhost:3000');
    });
    
How to Choose: cors vs @fastify/cors vs @koa/cors vs koa-cors
  • cors:

    Use cors if you are building an Express.js application or any Node.js server and need a widely adopted, flexible CORS middleware. It is highly configurable and supports a wide range of CORS scenarios, making it suitable for most applications.

  • @fastify/cors:

    Choose @fastify/cors if you are using the Fastify framework and need a highly performant, plugin-based CORS solution that integrates seamlessly with Fastify's architecture. It is optimized for speed and designed to work well with Fastify's asynchronous nature.

  • @koa/cors:

    Select @koa/cors if you are working with the Koa framework and want a simple, middleware-style CORS implementation. It is easy to use and configure, making it a good choice for Koa applications that require CORS support.

  • koa-cors:

    Consider koa-cors if you are using an older version of Koa (Koa 1.x) and need a lightweight CORS middleware. However, it is less maintained than @koa/cors, so it is recommended to use @koa/cors for newer projects.

README for cors

cors

NPM Version NPM Downloads Build Status Test Coverage

CORS is a node.js package for providing a Connect/Express middleware that can be used to enable CORS with various options.

Follow me (@troygoode) on Twitter!

Installation

This is a Node.js module available through the npm registry. Installation is done using the npm install command:

$ npm install cors

Usage

Simple Usage (Enable All CORS Requests)

var express = require('express')
var cors = require('cors')
var app = express()

app.use(cors())

app.get('/products/:id', function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for all origins!'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Enable CORS for a Single Route

var express = require('express')
var cors = require('cors')
var app = express()

app.get('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a Single Route'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Configuring CORS

var express = require('express')
var cors = require('cors')
var app = express()

var corsOptions = {
  origin: 'http://example.com',
  optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for only example.com.'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Configuring CORS w/ Dynamic Origin

var express = require('express')
var cors = require('cors')
var app = express()

var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
}

app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

If you do not want to block REST tools or server-to-server requests, add a !origin check in the origin function like so:

var corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1 || !origin) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
}

Enabling CORS Pre-Flight

Certain CORS requests are considered 'complex' and require an initial OPTIONS request (called the "pre-flight request"). An example of a 'complex' CORS request is one that uses an HTTP verb other than GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable pre-flighting, you must add a new OPTIONS handler for the route you want to support:

var express = require('express')
var cors = require('cors')
var app = express()

app.options('/products/:id', cors()) // enable pre-flight request for DELETE request
app.del('/products/:id', cors(), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for all origins!'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

You can also enable pre-flight across-the-board like so:

app.options('*', cors()) // include before other routes

Configuring CORS Asynchronously

var express = require('express')
var cors = require('cors')
var app = express()

var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptionsDelegate = function (req, callback) {
  var corsOptions;
  if (whitelist.indexOf(req.header('Origin')) !== -1) {
    corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
  } else {
    corsOptions = { origin: false } // disable CORS for this request
  }
  callback(null, corsOptions) // callback expects two parameters: error and options
}

app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})

app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

Configuration Options

  • origin: Configures the Access-Control-Allow-Origin CORS header. Possible values:
    • Boolean - set origin to true to reflect the request origin, as defined by req.header('Origin'), or set it to false to disable CORS.
    • String - set origin to a specific origin. For example if you set it to "http://example.com" only requests from "http://example.com" will be allowed.
    • RegExp - set origin to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern /example\.com$/ will reflect any request that is coming from an origin ending with "example.com".
    • Array - set origin to an array of valid origins. Each origin can be a String or a RegExp. For example ["http://example1.com", /\.example2\.com$/] will accept any request from "http://example1.com" or from a subdomain of "example2.com".
    • Function - set origin to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signature err [object], allow [bool]) as the second.
  • methods: Configures the Access-Control-Allow-Methods CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: ['GET', 'PUT', 'POST']).
  • allowedHeaders: Configures the Access-Control-Allow-Headers CORS header. Expects a comma-delimited string (ex: 'Content-Type,Authorization') or an array (ex: ['Content-Type', 'Authorization']). If not specified, defaults to reflecting the headers specified in the request's Access-Control-Request-Headers header.
  • exposedHeaders: Configures the Access-Control-Expose-Headers CORS header. Expects a comma-delimited string (ex: 'Content-Range,X-Content-Range') or an array (ex: ['Content-Range', 'X-Content-Range']). If not specified, no custom headers are exposed.
  • credentials: Configures the Access-Control-Allow-Credentials CORS header. Set to true to pass the header, otherwise it is omitted.
  • maxAge: Configures the Access-Control-Max-Age CORS header. Set to an integer to pass the header, otherwise it is omitted.
  • preflightContinue: Pass the CORS preflight response to the next handler.
  • optionsSuccessStatus: Provides a status code to use for successful OPTIONS requests, since some legacy browsers (IE11, various SmartTVs) choke on 204.

The default configuration is the equivalent of:

{
  "origin": "*",
  "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
  "preflightContinue": false,
  "optionsSuccessStatus": 204
}

For details on the effect of each CORS header, read this article on HTML5 Rocks.

Demo

A demo that illustrates CORS working (and not working) using jQuery is available here: http://node-cors-client.herokuapp.com/

Code for that demo can be found here:

License

MIT License

Author

Troy Goode (troygoode@gmail.com)