From e000fd0773d7242760da9ccb51959d307e49e653 Mon Sep 17 00:00:00 2001 From: alex94puchades Date: Tue, 26 May 2015 16:42:30 +0200 Subject: [PATCH 1/5] Allow regexp as options.origin --- lib/index.js | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/lib/index.js b/lib/index.js index d94bd32..2844fcb 100644 --- a/lib/index.js +++ b/lib/index.js @@ -12,23 +12,33 @@ preflightContinue: false }; + function varyHeadersOn(vary, headers) { + headers = Array.isArray(headers) ? headers.slice(0) : [headers]; + vary = Array.isArray(vary) ? vary : [vary]; + for (var i = 0; i < vary.length; ++i) + headers.push({ key: 'Vary', value: vary[i] }); + return headers; + } + function configureOrigin(options, req) { + var origin = req.headers.origin; if (!options.origin || options.origin === '*') { return { key: 'Access-Control-Allow-Origin', value: '*' }; } else { - return [ - { - key: 'Access-Control-Allow-Origin', - value: options.origin === true ? req.headers.origin : options.origin - }, - { - key: 'Vary', - value: 'Origin' - } - ]; + if (options.origin instanceof RegExp) { + return varyHeadersOn('Origin', { + key: 'Access-Control-Allow-Origin', + value: origin.match(opts.origin) ? origin : false + }); + } else { + return varyHeadersOn('Origin', { + key: 'Access-Control-Allow-Origin', + value: options.origin === true ? origin : options.origin + }); + } } } From 87f91d9609928ffbe192fb09fc2f046e5ec79858 Mon Sep 17 00:00:00 2001 From: Alejandro Caravaca Puchades Date: Wed, 27 May 2015 16:40:04 +0200 Subject: [PATCH 2/5] Use RegExp#test vs String#match --- lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/index.js b/lib/index.js index 2844fcb..0db3c50 100644 --- a/lib/index.js +++ b/lib/index.js @@ -31,7 +31,7 @@ if (options.origin instanceof RegExp) { return varyHeadersOn('Origin', { key: 'Access-Control-Allow-Origin', - value: origin.match(opts.origin) ? origin : false + value: opts.origin.test(origin) ? origin : false }); } else { return varyHeadersOn('Origin', { From 8ce16baead9039606ef4224258d6d2c1fad8ce39 Mon Sep 17 00:00:00 2001 From: Alejandro Caravaca Puchades Date: Thu, 28 May 2015 12:03:11 +0200 Subject: [PATCH 3/5] RegExp unit test added and fixed typo --- lib/index.js | 2 +- test/cors.js | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/index.js b/lib/index.js index 0db3c50..2e28c35 100644 --- a/lib/index.js +++ b/lib/index.js @@ -31,7 +31,7 @@ if (options.origin instanceof RegExp) { return varyHeadersOn('Origin', { key: 'Access-Control-Allow-Origin', - value: opts.origin.test(origin) ? origin : false + value: options.origin.test(origin) ? origin : false }); } else { return varyHeadersOn('Origin', { diff --git a/test/cors.js b/test/cors.js index 9920e03..08c7575 100644 --- a/test/cors.js +++ b/test/cors.js @@ -76,7 +76,7 @@ cors()(req, res, next); }); - it('don\'t shortcircuits preflight requests with preflightContinue option', function (done) { + it('doesn\'t shortcircuit preflight requests with preflightContinue option', function (done) { // arrange var req, res, next; req = fakeRequest(); @@ -186,6 +186,17 @@ cors(options)(req, res, next); }); + it('matches request origin against regexp', function(done) { + var req = fakeRequest(); + var res = fakeResponse(); + var options = { origin: /^(.+\.)?request.com$/ }; + cors(options)(req, res, function(err) { + should.not.exist(err); + res.getHeader('Access-Control-Allow-Origin').should.equal(req.headers.origin); + return done(); + }); + }); + it('origin of false disables cors', function (done) { // arrange var req, res, next, options; From 82a6cdf6ed2db73bcb216656929e4d089aba070d Mon Sep 17 00:00:00 2001 From: Alejandro Caravaca Puchades Date: Thu, 28 May 2015 22:43:16 +0200 Subject: [PATCH 4/5] Allow array of matching conditions as options.origin --- lib/index.js | 47 ++++++++++++++++++++++++++++++++++------------- test/cors.js | 13 +++++++++++++ 2 files changed, 47 insertions(+), 13 deletions(-) diff --git a/lib/index.js b/lib/index.js index 2e28c35..bb450e4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -13,32 +13,53 @@ }; function varyHeadersOn(vary, headers) { - headers = Array.isArray(headers) ? headers.slice(0) : [headers]; vary = Array.isArray(vary) ? vary : [vary]; + headers = Array.isArray(headers) ? headers.slice(0) : [headers]; for (var i = 0; i < vary.length; ++i) - headers.push({ key: 'Vary', value: vary[i] }); + headers.push({ key: 'Vary', value: vary[i] }); return headers; } + + function isString(what) { + return typeof what === 'string' || what instanceof String; + } + + function matchOrigin(origin, check) { + if (Array.isArray(check)) { + for (var i = 0; i < check.length; ++i) { + if (matchOrigin(origin, check[i])) + return true; + } + return false; + } else if (isString(check)) { + return origin === check; + } else if (check instanceof RegExp) { + return check.test(origin); + } else { + return !!check; + } + } function configureOrigin(options, req) { var origin = req.headers.origin; if (!options.origin || options.origin === '*') { + // allow any origin return { key: 'Access-Control-Allow-Origin', value: '*' }; + } else if (isString(options.origin)) { + // fixed origin + return varyHeadersOn('Origin', { + key: 'Access-Control-Allow-Origin', + value: options.origin + }); } else { - if (options.origin instanceof RegExp) { - return varyHeadersOn('Origin', { - key: 'Access-Control-Allow-Origin', - value: options.origin.test(origin) ? origin : false - }); - } else { - return varyHeadersOn('Origin', { - key: 'Access-Control-Allow-Origin', - value: options.origin === true ? origin : options.origin - }); - } + // reflect origin + return varyHeadersOn('Origin', { + key: 'Access-Control-Allow-Origin', + value: matchOrigin(origin, options.origin) ? origin : false + }); } } diff --git a/test/cors.js b/test/cors.js index 08c7575..f369863 100644 --- a/test/cors.js +++ b/test/cors.js @@ -193,6 +193,19 @@ cors(options)(req, res, function(err) { should.not.exist(err); res.getHeader('Access-Control-Allow-Origin').should.equal(req.headers.origin); + res.getHeader('Vary').should.equal('Origin'); + return done(); + }); + }); + + it('matches request origin against array of origin checks', function(done) { + var req = fakeRequest(); + var res = fakeResponse(); + var options = { origin: [ /foo\.com$/, 'request.com' ] }; + cors(options)(req, res, function(err) { + should.not.exist(err); + res.getHeader('Access-Control-Allow-Origin').should.equal(req.headers.origin); + res.getHeader('Vary').should.equal('Origin'); return done(); }); }); From 29d9bcb9301c88a9049ed51f421e4fac7612ee9f Mon Sep 17 00:00:00 2001 From: Alejandro Caravaca Puchades Date: Thu, 28 May 2015 22:58:26 +0200 Subject: [PATCH 5/5] Respect two-spaces indentation --- lib/index.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/index.js b/lib/index.js index bb450e4..f933f5c 100644 --- a/lib/index.js +++ b/lib/index.js @@ -13,11 +13,11 @@ }; function varyHeadersOn(vary, headers) { - vary = Array.isArray(vary) ? vary : [vary]; - headers = Array.isArray(headers) ? headers.slice(0) : [headers]; - for (var i = 0; i < vary.length; ++i) - headers.push({ key: 'Vary', value: vary[i] }); - return headers; + vary = Array.isArray(vary) ? vary : [vary]; + headers = Array.isArray(headers) ? headers.slice(0) : [headers]; + for (var i = 0; i < vary.length; ++i) + headers.push({ key: 'Vary', value: vary[i] }); + return headers; } function isString(what) {