Comparing version 0.5.0 to 1.0.0
16
api.js
@@ -6,3 +6,6 @@ module.exports = createApi | ||
, defaults = | ||
{ allowedDomains: [] | ||
{ checkOrigin: function (domain, cb) { | ||
// Allow all domains by default | ||
cb(null, true) | ||
} | ||
, logger: console | ||
@@ -24,2 +27,11 @@ } | ||
this._options = extend({}, defaults, options) | ||
// Support an array of allowedDomains for backwards compatibility | ||
if (Array.isArray(this._options.allowedDomains)) { | ||
this._options.checkOrigin = function (domain, cb) { | ||
if (this._options.allowedDomains.indexOf(domain) === -1) return cb(null, false) | ||
return cb(null, true) | ||
}.bind(this) | ||
} | ||
} | ||
@@ -53,2 +65,2 @@ | ||
} | ||
} | ||
} |
@@ -7,3 +7,3 @@ module.exports = createCorsMiddleware | ||
*/ | ||
function createCorsMiddleware(allowedDomains) { | ||
function createCorsMiddleware(checkDomain) { | ||
@@ -14,24 +14,24 @@ return function (req, res, next) { | ||
// Request origin is not in list of allowed domains | ||
if (allowedDomains.indexOf(req.headers.origin) === -1) return res.send(403) | ||
// Check if this client should be served | ||
checkDomain(req.headers.origin, function (err, allowed) { | ||
// Request came from allowed domain so set acces control headers | ||
res.set( | ||
{ 'Access-Control-Allow-Origin': '*' | ||
, 'Access-Control-Allow-Headers': 'Authorization, Content-Type, x-cf-date, *' | ||
, 'Access-Control-Request-Headers': '*' | ||
, 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, DELETE, PATCH' | ||
}) | ||
if (!allowed) return res.send(403) | ||
} | ||
// Request came from allowed domain so set acces control headers | ||
res.set( | ||
{ 'Access-Control-Allow-Origin': req.headers.origin | ||
, 'Access-Control-Allow-Headers': 'Authorization, Content-Type, x-cf-date, *' | ||
, 'Access-Control-Request-Headers': '*' | ||
, 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS, PUT, DELETE, PATCH' | ||
}) | ||
if (req.method === 'OPTIONS') { | ||
// Prefilght rarely changes so cache in proxies | ||
res.set('Cache-Control', 'max-age=86400') | ||
return res.end() | ||
next() | ||
}) | ||
} else { | ||
next() | ||
} | ||
next() | ||
} | ||
} |
@@ -5,3 +5,3 @@ { | ||
"description": "A pluggable JSON API server", | ||
"version": "0.5.0", | ||
"version": "1.0.0", | ||
"tags": [], | ||
@@ -8,0 +8,0 @@ "repository": { |
@@ -44,5 +44,7 @@ # cf-api | ||
- `allowedDomains` - a whitelist of allowed domains that cross-domain requests may come from (default: `[]`) | ||
- `checkOrigin` - a function with the signature `function (url, cb) {}` to check `req.headers.origin`. `cb(null, true)` to allow and `origin`, `cb(null, false)` to deny an origin. Defaults to `cb(null, true)` for all requests, meaning all cross-domain requests are allowed. It is up to the user to implement their whitelist/blacklist. | ||
- `logger` - a logger object with methods `debug()`, `info()`, `warn()` and `error()` (default: `console`) | ||
*For backwards compatibility, the `allowedDomains` option still works and generates a `checkOrigin` function for you.* | ||
### api.plugins(Array: plugins) or api.plugin(Function: plugin) | ||
@@ -69,2 +71,10 @@ | ||
## Changelog | ||
### 1.0.0 | ||
- Added `checkOrigin` option in place of `allowedDomains`. Latter is still supported for compatibility. | ||
### Pre 1.0.0 | ||
- Unstable! | ||
## Credits | ||
@@ -71,0 +81,0 @@ Built by developers at [Clock](http://clock.co.uk). |
@@ -39,3 +39,3 @@ module.exports = createServer | ||
// Whitelist cross domain requests | ||
.use(cors(options.allowedDomains)) | ||
.use(cors(options.checkOrigin)) | ||
@@ -60,2 +60,2 @@ // Body parse API for JSON content type | ||
} | ||
} |
@@ -21,2 +21,35 @@ var assert = require('assert') | ||
describe('cors', function () { | ||
it('should allow all domains by default', function (done) { | ||
var app = api() | ||
app._options.checkOrigin('anything goes!', function (err, allowed) { | ||
assert(allowed) | ||
done() | ||
}) | ||
}) | ||
it('should maintain backwards compatibility for allowedDomains option', function (done) { | ||
var app = api({ allowedDomains: [ 'a.com', 'b.com', 'c.com' ] }) | ||
, todo = 2 | ||
function finished() { | ||
if (--todo === 0) done() | ||
} | ||
app._options.checkOrigin('a.com', function (err, allowed) { | ||
assert(allowed) | ||
finished() | ||
}) | ||
app._options.checkOrigin('a.net', function (err, allowed) { | ||
assert(!allowed) | ||
finished() | ||
}) | ||
}) | ||
}) | ||
describe('plugins()', function () { | ||
@@ -88,2 +121,2 @@ | ||
}) | ||
}) |
var request = require('supertest') | ||
, assert = require('assert') | ||
, express = require('express') | ||
@@ -9,6 +8,11 @@ , createMiddleware = require('../../../middleware/cors') | ||
var app | ||
, allowed = [ 'http://127.0.0.1/' ] | ||
function checkOrigin(url, cb) { | ||
cb(null, allowed.indexOf(url) !== -1) | ||
} | ||
before(function () { | ||
app = express() | ||
app.use(createMiddleware([ 'http://127.0.0.1/' ])) | ||
app.use(createMiddleware(checkOrigin)) | ||
app.all('/', function (req, res) { | ||
@@ -39,13 +43,2 @@ res.send(200) | ||
it('should set cache headers on OPTIONS requests', function (done) { | ||
request(app) | ||
.options('/') | ||
.set('Origin', 'http://127.0.0.1/') | ||
.expect(200, function (err, res) { | ||
if (err) return done(err) | ||
assert.equal('max-age=86400', res.header['cache-control']) | ||
done() | ||
}) | ||
}) | ||
}) | ||
}) |
@@ -7,6 +7,8 @@ var assert = require('assert') | ||
it('should pass through if no origin header exists', function (done) { | ||
createMiddleware([])({ headers: {} }, {}, done) | ||
createMiddleware(function () { | ||
assert(false, 'checkOrigin() should not be called when req.headers.origin does not exist') | ||
})({ headers: {} }, {}, done) | ||
}) | ||
it('should send a 403 response to a request with an origin not in the allow list', function (done) { | ||
it('should send a 403 response when checkOrigin calls back with false', function (done) { | ||
@@ -18,3 +20,7 @@ function mockSend(statusCode) { | ||
createMiddleware([])({ headers: { origin: 'bar' } }, { send: mockSend }, function () { | ||
function checkOrigin(url, cb) { | ||
cb(null, false) | ||
} | ||
createMiddleware(checkOrigin)({ headers: { origin: 'bar' } }, { send: mockSend }, function () { | ||
assert(false, 'should not call next()') | ||
@@ -29,5 +35,9 @@ }) | ||
function checkOrigin(url, cb) { | ||
cb(null, allowed.indexOf(url) !== -1) | ||
} | ||
function mockSet(headers) { | ||
assert.deepEqual( | ||
{ 'Access-Control-Allow-Origin': '*' | ||
{ 'Access-Control-Allow-Origin': 'http://127.0.0.1/' | ||
, 'Access-Control-Allow-Headers': 'Authorization, Content-Type, x-cf-date, *' | ||
@@ -39,3 +49,3 @@ , 'Access-Control-Request-Headers': '*' | ||
createMiddleware(allowed)({ headers: { origin: allowed[0] } }, { set: mockSet }, function () { | ||
createMiddleware(checkOrigin)({ headers: { origin: allowed[0] } }, { set: mockSet }, function () { | ||
done() | ||
@@ -46,27 +56,2 @@ }) | ||
it('should set cache headers on OPTIONS requests', function (done) { | ||
var allowed = [ 'http://127.0.0.1/' ] | ||
, count = 0 | ||
function mockSet(header, value) { | ||
if (++count === 2) { | ||
assert.equal('Cache-Control', header) | ||
assert.equal('max-age=86400', value) | ||
} | ||
} | ||
function mockEnd() { | ||
done() | ||
} | ||
var req = { headers: { origin: allowed[0] }, method: 'OPTIONS' } | ||
, res = { set: mockSet, end: mockEnd } | ||
createMiddleware(allowed)(req, res, function () { | ||
assert(false, 'should not call next()') | ||
}) | ||
}) | ||
}) | ||
}) |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
27410
696
1
83