Skip to content

expressjs/cors

Repository files navigation

cors

NPM Version NPM Downloads Build Status Test Coverage

CORS is a node.js package for providing aConnect/Expressmiddleware that can be used to enableCORSwith various options.

Follow me (@troygoode) on Twitter!

Installation

This is aNode.jsmodule available through the npm registry.Installation is done using the npm installcommand:

$ npm install cors

Usage

Simple Usage (EnableAllCORS Requests)

varexpress=require('express')
varcors=require('cors')
varapp=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

varexpress=require('express')
varcors=require('cors')
varapp=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

varexpress=require('express')
varcors=require('cors')
varapp=express()

varcorsOptions={
origin:'http://example ',
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.'})
})

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

Configuring CORS w/ Dynamic Origin

This module supports validating the origin dynamically using a function provided to theoriginoption. This function will be passed a string that is the origin (orundefinedif the request has no origin), and acallbackwith the signature callback(error, origin).

Theoriginargument to the callback can be any value allowed for theorigin option of the middleware, except a function. See the configuration optionssection for more information on all the possible value types.

This function is designed to allow the dynamic loading of allowed origin(s) from a backing datasource, like a database.

varexpress=require('express')
varcors=require('cors')
varapp=express()

varcorsOptions={
origin:function(origin,callback){
// db.loadOrigins is an example call to load
// a list of origins from a backing database
db.loadOrigins(function(error,origins){
callback(error,origins)
})
}
}

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

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

Enabling CORS Pre-Flight

Certain CORS requests are considered 'complex' and require an initial OPTIONSrequest (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:

varexpress=require('express')
varcors=require('cors')
varapp=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

NOTE: When using this middleware as an application level middleware (for example,app.use(cors())), pre-flight requests are already handled for all routes.

Configuring CORS Asynchronously

varexpress=require('express')
varcors=require('cors')
varapp=express()

varallowlist=['http://example1 ','http://example2 ']
varcorsOptionsDelegate=function(req,callback){
varcorsOptions;
if(allowlist.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 an allowed domain.'})
})

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

Configuration Options

  • origin:Configures theAccess-Control-Allow-OriginCORS header. Possible values:
    • Boolean- setorigintotrueto reflect therequest origin,as defined byreq.header('Origin'),or set it tofalseto disable CORS.
    • String- setoriginto a specific origin. For example if you set it to"http://example"only requests from "http://example"will be allowed.
    • RegExp- setoriginto 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\ $/will reflect any request that is coming from an origin ending with "example".
    • Array- setoriginto an array of valid origins. Each origin can be aStringor aRegExp.For example[ "http://example1", /\.example2\ $/]will accept any request from "http://example1"or from a subdomain of" example2 ".
    • Function- setoriginto a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (called ascallback(err, origin),whereoriginis a non-function value of theoriginoption) as the second.
  • methods:Configures theAccess-Control-Allow-MethodsCORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex:['GET', 'PUT', 'POST']).
  • allowedHeaders:Configures theAccess-Control-Allow-HeadersCORS 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'sAccess-Control-Request-Headersheader.
  • exposedHeaders:Configures theAccess-Control-Expose-HeadersCORS 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 theAccess-Control-Allow-CredentialsCORS header. Set totrueto pass the header, otherwise it is omitted.
  • maxAge:Configures theAccess-Control-Max-AgeCORS 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 successfulOPTIONSrequests, since some legacy browsers (IE11, various SmartTVs) choke on204.

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, readthisarticle on web.dev.

Demo

A demo that illustrates CORS working (and not working) using React is available here:https://node-cors-client.netlify

Code for that demo can be found here:

License

MIT License

Author

Troy Goode(troygoode@gmail)