parent
c41ee12da8
commit
b99cfa4e01
@ -0,0 +1,33 @@
|
|||||||
|
# contributing to `cors`
|
||||||
|
|
||||||
|
CORS is a node.js package for providing a [connect](http://www.senchalabs.org/connect/)/[express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options. Learn more about the project in [the README](README.md).
|
||||||
|
|
||||||
|
## The CORS Spec
|
||||||
|
|
||||||
|
[http://www.w3.org/TR/cors/](http://www.w3.org/TR/cors/)
|
||||||
|
|
||||||
|
## Pull Requests Welcome
|
||||||
|
|
||||||
|
* Include `'use strict';` in every javascript file.
|
||||||
|
* 2 space indentation.
|
||||||
|
* Please run the testing steps below before submitting.
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install
|
||||||
|
$ npm test
|
||||||
|
```
|
||||||
|
|
||||||
|
## Interactive Testing Harness
|
||||||
|
|
||||||
|
[http://node-cors-client.herokuapp.com](http://node-cors-client.herokuapp.com)
|
||||||
|
|
||||||
|
Related git repositories:
|
||||||
|
|
||||||
|
* [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server)
|
||||||
|
* [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
2.8.5 / 2018-11-04
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix setting `maxAge` option to `0`
|
||||||
|
|
||||||
|
2.8.4 / 2017-07-12
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Work-around Safari bug in default pre-flight response
|
||||||
|
|
||||||
|
2.8.3 / 2017-03-29
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix error when options delegate missing `methods` option
|
||||||
|
|
||||||
|
2.8.2 / 2017-03-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix error when frozen options are passed
|
||||||
|
* Send "Vary: Origin" when using regular expressions
|
||||||
|
* Send "Vary: Access-Control-Request-Headers" when dynamic `allowedHeaders`
|
||||||
|
|
||||||
|
2.8.1 / 2016-09-08
|
||||||
|
==================
|
||||||
|
|
||||||
|
This release only changed documentation.
|
||||||
|
|
||||||
|
2.8.0 / 2016-08-23
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Add `optionsSuccessStatus` option
|
||||||
|
|
||||||
|
2.7.2 / 2016-08-23
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Fix error when Node.js running in strict mode
|
||||||
|
|
||||||
|
2.7.1 / 2015-05-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Move module into expressjs organization
|
||||||
|
|
||||||
|
2.7.0 / 2015-05-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Allow array of matching condition as `origin` option
|
||||||
|
* Allow regular expression as `origin` option
|
||||||
|
|
||||||
|
2.6.1 / 2015-05-28
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Update `license` in package.json
|
||||||
|
|
||||||
|
2.6.0 / 2015-04-27
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Add `preflightContinue` option
|
||||||
|
* Fix "Vary: Origin" header added for "*"
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2013 Troy Goode <troygoode@gmail.com>
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
'Software'), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
@ -0,0 +1,243 @@
|
|||||||
|
# cors
|
||||||
|
|
||||||
|
[![NPM Version][npm-image]][npm-url]
|
||||||
|
[![NPM Downloads][downloads-image]][downloads-url]
|
||||||
|
[![Build Status][travis-image]][travis-url]
|
||||||
|
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||||
|
|
||||||
|
CORS is a node.js package for providing a [Connect](http://www.senchalabs.org/connect/)/[Express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options.
|
||||||
|
|
||||||
|
**[Follow me (@troygoode) on Twitter!](https://twitter.com/intent/user?screen_name=troygoode)**
|
||||||
|
|
||||||
|
* [Installation](#installation)
|
||||||
|
* [Usage](#usage)
|
||||||
|
* [Simple Usage](#simple-usage-enable-all-cors-requests)
|
||||||
|
* [Enable CORS for a Single Route](#enable-cors-for-a-single-route)
|
||||||
|
* [Configuring CORS](#configuring-cors)
|
||||||
|
* [Configuring CORS Asynchronously](#configuring-cors-asynchronously)
|
||||||
|
* [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)
|
||||||
|
* [Configuration Options](#configuration-options)
|
||||||
|
* [Demo](#demo)
|
||||||
|
* [License](#license)
|
||||||
|
* [Author](#author)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
This is a [Node.js](https://nodejs.org/en/) module available through the
|
||||||
|
[npm registry](https://www.npmjs.com/). Installation is done using the
|
||||||
|
[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ npm install cors
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Simple Usage (Enable *All* CORS Requests)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
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
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
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
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
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
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
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:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
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:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
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:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
app.options('*', cors()) // include before other routes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configuring CORS Asynchronously
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
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](http://tools.ietf.org/html/draft-abarth-origin-09), 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:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"origin": "*",
|
||||||
|
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
|
||||||
|
"preflightContinue": false,
|
||||||
|
"optionsSuccessStatus": 204
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
For details on the effect of each CORS header, read [this](http://www.html5rocks.com/en/tutorials/cors/) 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/](http://node-cors-client.herokuapp.com/)
|
||||||
|
|
||||||
|
Code for that demo can be found here:
|
||||||
|
|
||||||
|
* Client: [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client)
|
||||||
|
* Server: [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[MIT License](http://www.opensource.org/licenses/mit-license.php)
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
[Troy Goode](https://github.com/TroyGoode) ([troygoode@gmail.com](mailto:troygoode@gmail.com))
|
||||||
|
|
||||||
|
[coveralls-image]: https://img.shields.io/coveralls/expressjs/cors/master.svg
|
||||||
|
[coveralls-url]: https://coveralls.io/r/expressjs/cors?branch=master
|
||||||
|
[downloads-image]: https://img.shields.io/npm/dm/cors.svg
|
||||||
|
[downloads-url]: https://npmjs.org/package/cors
|
||||||
|
[npm-image]: https://img.shields.io/npm/v/cors.svg
|
||||||
|
[npm-url]: https://npmjs.org/package/cors
|
||||||
|
[travis-image]: https://img.shields.io/travis/expressjs/cors/master.svg
|
||||||
|
[travis-url]: https://travis-ci.org/expressjs/cors
|
||||||
@ -0,0 +1,238 @@
|
|||||||
|
(function () {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var assign = require('object-assign');
|
||||||
|
var vary = require('vary');
|
||||||
|
|
||||||
|
var defaults = {
|
||||||
|
origin: '*',
|
||||||
|
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
|
||||||
|
preflightContinue: false,
|
||||||
|
optionsSuccessStatus: 204
|
||||||
|
};
|
||||||
|
|
||||||
|
function isString(s) {
|
||||||
|
return typeof s === 'string' || s instanceof String;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isOriginAllowed(origin, allowedOrigin) {
|
||||||
|
if (Array.isArray(allowedOrigin)) {
|
||||||
|
for (var i = 0; i < allowedOrigin.length; ++i) {
|
||||||
|
if (isOriginAllowed(origin, allowedOrigin[i])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else if (isString(allowedOrigin)) {
|
||||||
|
return origin === allowedOrigin;
|
||||||
|
} else if (allowedOrigin instanceof RegExp) {
|
||||||
|
return allowedOrigin.test(origin);
|
||||||
|
} else {
|
||||||
|
return !!allowedOrigin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureOrigin(options, req) {
|
||||||
|
var requestOrigin = req.headers.origin,
|
||||||
|
headers = [],
|
||||||
|
isAllowed;
|
||||||
|
|
||||||
|
if (!options.origin || options.origin === '*') {
|
||||||
|
// allow any origin
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Origin',
|
||||||
|
value: '*'
|
||||||
|
}]);
|
||||||
|
} else if (isString(options.origin)) {
|
||||||
|
// fixed origin
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Origin',
|
||||||
|
value: options.origin
|
||||||
|
}]);
|
||||||
|
headers.push([{
|
||||||
|
key: 'Vary',
|
||||||
|
value: 'Origin'
|
||||||
|
}]);
|
||||||
|
} else {
|
||||||
|
isAllowed = isOriginAllowed(requestOrigin, options.origin);
|
||||||
|
// reflect origin
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Origin',
|
||||||
|
value: isAllowed ? requestOrigin : false
|
||||||
|
}]);
|
||||||
|
headers.push([{
|
||||||
|
key: 'Vary',
|
||||||
|
value: 'Origin'
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureMethods(options) {
|
||||||
|
var methods = options.methods;
|
||||||
|
if (methods.join) {
|
||||||
|
methods = options.methods.join(','); // .methods is an array, so turn it into a string
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Allow-Methods',
|
||||||
|
value: methods
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureCredentials(options) {
|
||||||
|
if (options.credentials === true) {
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Allow-Credentials',
|
||||||
|
value: 'true'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureAllowedHeaders(options, req) {
|
||||||
|
var allowedHeaders = options.allowedHeaders || options.headers;
|
||||||
|
var headers = [];
|
||||||
|
|
||||||
|
if (!allowedHeaders) {
|
||||||
|
allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
|
||||||
|
headers.push([{
|
||||||
|
key: 'Vary',
|
||||||
|
value: 'Access-Control-Request-Headers'
|
||||||
|
}]);
|
||||||
|
} else if (allowedHeaders.join) {
|
||||||
|
allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string
|
||||||
|
}
|
||||||
|
if (allowedHeaders && allowedHeaders.length) {
|
||||||
|
headers.push([{
|
||||||
|
key: 'Access-Control-Allow-Headers',
|
||||||
|
value: allowedHeaders
|
||||||
|
}]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureExposedHeaders(options) {
|
||||||
|
var headers = options.exposedHeaders;
|
||||||
|
if (!headers) {
|
||||||
|
return null;
|
||||||
|
} else if (headers.join) {
|
||||||
|
headers = headers.join(','); // .headers is an array, so turn it into a string
|
||||||
|
}
|
||||||
|
if (headers && headers.length) {
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Expose-Headers',
|
||||||
|
value: headers
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function configureMaxAge(options) {
|
||||||
|
var maxAge = (typeof options.maxAge === 'number' || options.maxAge) && options.maxAge.toString()
|
||||||
|
if (maxAge && maxAge.length) {
|
||||||
|
return {
|
||||||
|
key: 'Access-Control-Max-Age',
|
||||||
|
value: maxAge
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyHeaders(headers, res) {
|
||||||
|
for (var i = 0, n = headers.length; i < n; i++) {
|
||||||
|
var header = headers[i];
|
||||||
|
if (header) {
|
||||||
|
if (Array.isArray(header)) {
|
||||||
|
applyHeaders(header, res);
|
||||||
|
} else if (header.key === 'Vary' && header.value) {
|
||||||
|
vary(res, header.value);
|
||||||
|
} else if (header.value) {
|
||||||
|
res.setHeader(header.key, header.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cors(options, req, res, next) {
|
||||||
|
var headers = [],
|
||||||
|
method = req.method && req.method.toUpperCase && req.method.toUpperCase();
|
||||||
|
|
||||||
|
if (method === 'OPTIONS') {
|
||||||
|
// preflight
|
||||||
|
headers.push(configureOrigin(options, req));
|
||||||
|
headers.push(configureCredentials(options, req));
|
||||||
|
headers.push(configureMethods(options, req));
|
||||||
|
headers.push(configureAllowedHeaders(options, req));
|
||||||
|
headers.push(configureMaxAge(options, req));
|
||||||
|
headers.push(configureExposedHeaders(options, req));
|
||||||
|
applyHeaders(headers, res);
|
||||||
|
|
||||||
|
if (options.preflightContinue) {
|
||||||
|
next();
|
||||||
|
} else {
|
||||||
|
// Safari (and potentially other browsers) need content-length 0,
|
||||||
|
// for 204 or they just hang waiting for a body
|
||||||
|
res.statusCode = options.optionsSuccessStatus;
|
||||||
|
res.setHeader('Content-Length', '0');
|
||||||
|
res.end();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// actual response
|
||||||
|
headers.push(configureOrigin(options, req));
|
||||||
|
headers.push(configureCredentials(options, req));
|
||||||
|
headers.push(configureExposedHeaders(options, req));
|
||||||
|
applyHeaders(headers, res);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function middlewareWrapper(o) {
|
||||||
|
// if options are static (either via defaults or custom options passed in), wrap in a function
|
||||||
|
var optionsCallback = null;
|
||||||
|
if (typeof o === 'function') {
|
||||||
|
optionsCallback = o;
|
||||||
|
} else {
|
||||||
|
optionsCallback = function (req, cb) {
|
||||||
|
cb(null, o);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return function corsMiddleware(req, res, next) {
|
||||||
|
optionsCallback(req, function (err, options) {
|
||||||
|
if (err) {
|
||||||
|
next(err);
|
||||||
|
} else {
|
||||||
|
var corsOptions = assign({}, defaults, options);
|
||||||
|
var originCallback = null;
|
||||||
|
if (corsOptions.origin && typeof corsOptions.origin === 'function') {
|
||||||
|
originCallback = corsOptions.origin;
|
||||||
|
} else if (corsOptions.origin) {
|
||||||
|
originCallback = function (origin, cb) {
|
||||||
|
cb(null, corsOptions.origin);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originCallback) {
|
||||||
|
originCallback(req.headers.origin, function (err2, origin) {
|
||||||
|
if (err2 || !origin) {
|
||||||
|
next(err2);
|
||||||
|
} else {
|
||||||
|
corsOptions.origin = origin;
|
||||||
|
cors(corsOptions, req, res, next);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// can pass either an options hash, an options delegate, or nothing
|
||||||
|
module.exports = middlewareWrapper;
|
||||||
|
|
||||||
|
}());
|
||||||
@ -0,0 +1,78 @@
|
|||||||
|
{
|
||||||
|
"_from": "cors",
|
||||||
|
"_id": "cors@2.8.5",
|
||||||
|
"_inBundle": false,
|
||||||
|
"_integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||||
|
"_location": "/cors",
|
||||||
|
"_phantomChildren": {},
|
||||||
|
"_requested": {
|
||||||
|
"type": "tag",
|
||||||
|
"registry": true,
|
||||||
|
"raw": "cors",
|
||||||
|
"name": "cors",
|
||||||
|
"escapedName": "cors",
|
||||||
|
"rawSpec": "",
|
||||||
|
"saveSpec": null,
|
||||||
|
"fetchSpec": "latest"
|
||||||
|
},
|
||||||
|
"_requiredBy": [
|
||||||
|
"#USER",
|
||||||
|
"/"
|
||||||
|
],
|
||||||
|
"_resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||||
|
"_shasum": "eac11da51592dd86b9f06f6e7ac293b3df875d29",
|
||||||
|
"_spec": "cors",
|
||||||
|
"_where": "D:\\Development\\FintechSG\\fullstackapp\\backend",
|
||||||
|
"author": {
|
||||||
|
"name": "Troy Goode",
|
||||||
|
"email": "troygoode@gmail.com",
|
||||||
|
"url": "https://github.com/troygoode/"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/expressjs/cors/issues"
|
||||||
|
},
|
||||||
|
"bundleDependencies": false,
|
||||||
|
"dependencies": {
|
||||||
|
"object-assign": "^4",
|
||||||
|
"vary": "^1"
|
||||||
|
},
|
||||||
|
"deprecated": false,
|
||||||
|
"description": "Node.js CORS middleware",
|
||||||
|
"devDependencies": {
|
||||||
|
"after": "0.8.2",
|
||||||
|
"eslint": "2.13.1",
|
||||||
|
"express": "4.16.3",
|
||||||
|
"mocha": "5.2.0",
|
||||||
|
"nyc": "13.1.0",
|
||||||
|
"supertest": "3.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.10"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"lib/index.js",
|
||||||
|
"CONTRIBUTING.md",
|
||||||
|
"HISTORY.md",
|
||||||
|
"LICENSE",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/expressjs/cors#readme",
|
||||||
|
"keywords": [
|
||||||
|
"cors",
|
||||||
|
"express",
|
||||||
|
"connect",
|
||||||
|
"middleware"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "./lib/index.js",
|
||||||
|
"name": "cors",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/expressjs/cors.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"lint": "eslint lib test",
|
||||||
|
"test": "npm run lint && nyc --reporter=html --reporter=text mocha --require test/support/env"
|
||||||
|
},
|
||||||
|
"version": "2.8.5"
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue