From ebc2f68a43158a7f2c4f3fa18fdbcbe14b83b4d7 Mon Sep 17 00:00:00 2001 From: Andrey Senaev Date: Thu, 22 Mar 2018 16:42:08 +0500 Subject: [PATCH 1/3] add support for credentials requests --- README.md | 2 ++ bin/http-server | 7 +++++++ lib/http-server.js | 14 +++++++++++--- test/http-server-test.js | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 74d57a6c6..774c970d4 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ This will install `http-server` globally so that it may be run from the command `--cors` Enable CORS via the `Access-Control-Allow-Origin` header +`--credentials` Cookie credentials can be transferred as part of a CORS request (enables --cors automatically) + `-o` Open browser window after starting the server `-c` Set cache time (in seconds) for cache-control max-age header, e.g. -c10 for 10 seconds (defaults to '3600'). To disable caching, use -c-1. diff --git a/bin/http-server b/bin/http-server index 926e0dd75..3b2b47ebc 100755 --- a/bin/http-server +++ b/bin/http-server @@ -9,6 +9,7 @@ var colors = require('colors/safe'), opener = require('opener'), argv = require('optimist') .boolean('cors') + .boolean('credentials') .argv; var ifaces = os.networkInterfaces(); @@ -27,6 +28,8 @@ if (argv.h || argv.help) { ' -s --silent Suppress log messages from output', ' --cors[=headers] Enable CORS via the "Access-Control-Allow-Origin" header', ' Optionally provide CORS headers list separated by commas', + ' --credentials Cookie credentials can be transferred as part of a CORS request', + ' Enables --cors automatically', ' -o [path] Open browser window after starting the server', ' -c Cache time (max-age) in seconds [3600], e.g. -c10 for 10 seconds.', ' To disable caching, use -c-1.', @@ -113,6 +116,10 @@ function listen(port) { } } + if (argv.credentials) { + options.credentials = true; + } + if (ssl) { options.https = { cert: argv.C || argv.cert || 'cert.pem', diff --git a/lib/http-server.js b/lib/http-server.js index 7e3e06df1..b7b08ee28 100644 --- a/lib/http-server.js +++ b/lib/http-server.js @@ -66,16 +66,24 @@ function HttpServer(options) { res.emit('next'); }); - if (options.cors) { + if (options.cors || options.credentials) { this.headers['Access-Control-Allow-Origin'] = '*'; this.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Range'; if (options.corsHeaders) { options.corsHeaders.split(/\s*,\s*/) .forEach(function (h) { this.headers['Access-Control-Allow-Headers'] += ', ' + h; }, this); } - before.push(corser.create(options.corsHeaders ? { + + var corserOptions = options.corsHeaders ? { requestHeaders: this.headers['Access-Control-Allow-Headers'].split(/\s*,\s*/) - } : null)); + } : {}; + + if (options.credentials) { + corserOptions.supportsCredentials = true; + this.headers['Access-Control-Allow-Credentials'] = 'true'; + } + + before.push(corser.create(corserOptions)); } if (options.robots) { diff --git a/test/http-server-test.js b/test/http-server-test.js index e64f04e1d..24b346b4c 100644 --- a/test/http-server-test.js +++ b/test/http-server-test.js @@ -152,6 +152,43 @@ vows.describe('http-server').addBatch({ }, 'response Access-Control-Allow-Headers should contain X-Test': function (err, res) { assert.ok(res.headers['access-control-allow-headers'].split(/\s*,\s*/g).indexOf('X-Test') >= 0, 204); + }, + 'response Access-Control-Allow-Credentials should not be presented': function (err, res) { + assert.equal(res.headers['access-control-allow-credentials'], undefined); + } + } + }, + 'When credentials is enabled': { + topic: function () { + var server = httpServer.createServer({ + root: root, + credentials: true, + corsHeaders: 'X-Test' + }); + server.listen(8083); + this.callback(null, server); + }, + 'and given OPTIONS request': { + topic: function () { + request({ + method: 'OPTIONS', + uri: 'http://127.0.0.1:8083/', + headers: { + 'Access-Control-Request-Method': 'GET', + Origin: 'http://example.com', + 'Access-Control-Request-Headers': 'Foobar', + Cookie: 'cookie' + } + }, this.callback); + }, + 'status code should be 204': function (err, res) { + assert.equal(res.statusCode, 204); + }, + 'response Access-Control-Allow-Headers should contain X-Test': function (err, res) { + assert.ok(res.headers['access-control-allow-headers'].split(/\s*,\s*/g).indexOf('X-Test') >= 0, 204); + }, + 'response Access-Control-Allow-Credentials should be true': function (err, res) { + assert.equal(res.headers['access-control-allow-credentials'], 'true'); } } } From 7dd80bb1c0ea0ee366951e3e1f20b040313977f7 Mon Sep 17 00:00:00 2001 From: Andrey Senaev Date: Mon, 26 Mar 2018 15:04:23 +0500 Subject: [PATCH 2/3] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 774c970d4..1c10bca44 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ This will install `http-server` globally so that it may be run from the command `--cors` Enable CORS via the `Access-Control-Allow-Origin` header -`--credentials` Cookie credentials can be transferred as part of a CORS request (enables --cors automatically) +`--credentials` Cookie credentials can be transferred as part of a CORS request (enables `--cors` automatically) `-o` Open browser window after starting the server From b7e4dc152d6223296bb5f0f35fcd9087559fc0d1 Mon Sep 17 00:00:00 2001 From: Andrey Senaev Date: Fri, 19 Apr 2019 16:49:42 +0300 Subject: [PATCH 3/3] cr --- test/http-server-test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/http-server-test.js b/test/http-server-test.js index d039d2d25..4a543d8ab 100644 --- a/test/http-server-test.js +++ b/test/http-server-test.js @@ -168,14 +168,14 @@ vows.describe('http-server').addBatch({ credentials: true, corsHeaders: 'X-Test' }); - server.listen(8083); + server.listen(8085); this.callback(null, server); }, 'and given OPTIONS request': { topic: function () { request({ method: 'OPTIONS', - uri: 'http://127.0.0.1:8083/', + uri: 'http://127.0.0.1:8085/', headers: { 'Access-Control-Request-Method': 'GET', Origin: 'http://example.com',