From 227b0a359367bd0f1f522385f1bc0a456c657b39 Mon Sep 17 00:00:00 2001 From: Ran Ding Date: Mon, 6 Nov 2023 21:53:40 +1100 Subject: [PATCH] feat: handle Chrome CORS preflight private network header --- README.md | 1 + lib/index.js | 15 +++++++++++++++ test/test.js | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/README.md b/README.md index c42d4a7..4b7057c 100644 --- a/README.md +++ b/README.md @@ -204,6 +204,7 @@ app.listen(80, function () { * `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`. +* `allowPrivateNetwork`: Provides **Access-Control-Allow-Private-Network: true** if **Access-Control-Request-Private-Network: true** is presented. The default configuration is the equivalent of: diff --git a/lib/index.js b/lib/index.js index ad899ca..3e6f102 100644 --- a/lib/index.js +++ b/lib/index.js @@ -156,6 +156,20 @@ } } + function configureAllowPrivateNetwork(options, req) { + var reqHeader = req.headers['access-control-request-private-network']; + if ( + options.allowPrivateNetwork && + reqHeader && reqHeader === 'true' + ) { + return { + key: 'Access-Control-Allow-Private-Network', + value: 'true', + }; + } + return null; + } + function cors(options, req, res, next) { var headers = [], method = req.method && req.method.toUpperCase && req.method.toUpperCase(); @@ -168,6 +182,7 @@ headers.push(configureAllowedHeaders(options, req)); headers.push(configureMaxAge(options)) headers.push(configureExposedHeaders(options)) + headers.push(configureAllowPrivateNetwork(options, req)); applyHeaders(headers, res); if (options.preflightContinue) { diff --git a/test/test.js b/test/test.js index f2a2e94..9a476f8 100644 --- a/test/test.js +++ b/test/test.js @@ -571,6 +571,39 @@ var util = require('util') }) }); + it('allows private network if explicitly enabled', function (done) { + var cb = after(1, done) + var req = new FakeRequest('OPTIONS', { + 'access-control-request-private-network': 'true' + }) + var res = new FakeResponse() + + res.on('finish', function () { + assert.equal(res.getHeader('Access-Control-Allow-Private-Network'), 'true') + cb() + }) + + cors({ allowPrivateNetwork: true })(req, res, function (err) { + cb(err || new Error('should not be called')) + }) + }); + + + it('not allows private network if explicitly enabled but access-control-request-private-network is missing', function (done) { + var cb = after(1, done) + var req = new FakeRequest('OPTIONS') + var res = new FakeResponse() + + res.on('finish', function () { + assert.equal(res.getHeader('Access-Control-Allow-Private-Network'), undefined) + cb() + }) + + cors({ allowPrivateNetwork: true })(req, res, function (err) { + cb(err || new Error('should not be called')) + }) + }); + it('does not includes credentials unless explicitly enabled', function (done) { // arrange var req, res, next;