From f17a7c8452ded04debcc4ff483570e41f58e0547 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Fri, 28 Sep 2018 14:58:30 -0400 Subject: [PATCH 1/3] add support for CORS --- bin/serve.js | 7 ++++++- src/app/server/coerce-opts.js | 1 + src/app/server/create-server.js | 11 +++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/bin/serve.js b/bin/serve.js index 7ff44123..aad32b11 100755 --- a/bin/serve.js +++ b/bin/serve.js @@ -40,6 +40,10 @@ const OPTS_META = [].concat([{ name: 'debug', type: 'boolean', description: 'Starts app in debug mode.' +}, { + name: 'cors', + type: 'boolean', + description: 'Enables Cross-Origin Resource Sharing (CORS)' }]) const HELP_MSG = `orca serve @@ -109,7 +113,8 @@ function main (args) { port: opts.port, maxNumberOfWindows: opts.maxNumberOfWindows, debug: opts.debug, - component: component + component: component, + cors: opts.cors }) app.on('after-connect', (info) => { diff --git a/src/app/server/coerce-opts.js b/src/app/server/coerce-opts.js index de4001c4..ae90b93e 100644 --- a/src/app/server/coerce-opts.js +++ b/src/app/server/coerce-opts.js @@ -23,6 +23,7 @@ function coerceOpts (_opts = {}) { : cst.dflt.maxNumberOfWindows opts.debug = !!_opts.debug + opts.cors = !!_opts.cors opts._browserWindowOpts = { show: !!opts.debug } const _components = Array.isArray(_opts.component) ? _opts.component : [_opts.component] diff --git a/src/app/server/create-server.js b/src/app/server/create-server.js index 6afb9086..98daf322 100644 --- a/src/app/server/create-server.js +++ b/src/app/server/create-server.js @@ -52,6 +52,17 @@ function createServer (app, BrowserWindow, ipcMain, opts) { return simpleReply(code, fullInfo.msg) } + // Set CORS headers + if (opts.cors) { + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Request-Method', '*'); + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET', 'POST'); + res.setHeader('Access-Control-Allow-Headers', '*'); + if (req.method === 'OPTIONS') { + return simpleReply(200) + } + } + req.once('error', () => simpleReply(401)) req.once('close', () => simpleReply(499)) From 91a794f5bf81263467d4f0559e743daf24321281 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Fri, 28 Sep 2018 15:16:00 -0400 Subject: [PATCH 2/3] fix syntax --- src/app/server/create-server.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/server/create-server.js b/src/app/server/create-server.js index 98daf322..ff70f6a1 100644 --- a/src/app/server/create-server.js +++ b/src/app/server/create-server.js @@ -54,10 +54,10 @@ function createServer (app, BrowserWindow, ipcMain, opts) { // Set CORS headers if (opts.cors) { - res.setHeader('Access-Control-Allow-Origin', '*'); - res.setHeader('Access-Control-Request-Method', '*'); - res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET', 'POST'); - res.setHeader('Access-Control-Allow-Headers', '*'); + res.setHeader('Access-Control-Allow-Origin', '*') + res.setHeader('Access-Control-Request-Method', '*') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET', 'POST') + res.setHeader('Access-Control-Allow-Headers', '*') if (req.method === 'OPTIONS') { return simpleReply(200) } From 842a115948099c6952f3a564b7901efad5552c38 Mon Sep 17 00:00:00 2001 From: Antoine Roy-Gobeil Date: Fri, 28 Sep 2018 18:57:01 -0400 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=94=92=20down=20CORS=20with=20unit=20?= =?UTF-8?q?test?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/server/create-server.js | 3 +-- test/unit/server_test.js | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/app/server/create-server.js b/src/app/server/create-server.js index ff70f6a1..bc306a70 100644 --- a/src/app/server/create-server.js +++ b/src/app/server/create-server.js @@ -55,8 +55,7 @@ function createServer (app, BrowserWindow, ipcMain, opts) { // Set CORS headers if (opts.cors) { res.setHeader('Access-Control-Allow-Origin', '*') - res.setHeader('Access-Control-Request-Method', '*') - res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET', 'POST') + res.setHeader('Access-Control-Allow-Methods', 'OPTIONS, GET, POST') res.setHeader('Access-Control-Allow-Headers', '*') if (req.method === 'OPTIONS') { return simpleReply(200) diff --git a/test/unit/server_test.js b/test/unit/server_test.js index a407d202..6a93df6a 100644 --- a/test/unit/server_test.js +++ b/test/unit/server_test.js @@ -44,6 +44,7 @@ tap.test('coerceOpts:', t => { t.equal(out.port, 1000, 'port') t.equal(out.debug, false, 'debug') + t.equal(out.cors, false, 'cors') t.equal(out.maxNumberOfWindows, 50, 'maxNumberOfWindows') t.end() }) @@ -97,6 +98,15 @@ tap.test('createServer:', t => { } }) + const optsCors = () => coerceOpts({ + cors: true, + port: 8001, + component: { + name: 'plotly-graph', + route: '/' + } + }) + const body0 = () => JSON.stringify({ figure: { data: [{ y: [1, 2, 1] }] @@ -143,6 +153,34 @@ tap.test('createServer:', t => { }) }) + t.test('should reply with access-control-* headers when CORS is enabled', t => { + _boot([false, false, false, optsCors()], () => { + _post('', '', (err, res, body) => { + if (err) t.fail(err) + t.equal(res.headers['access-control-allow-origin'], '*') + t.equal(res.headers['access-control-allow-headers'], '*') + t.match(res.headers['access-control-allow-methods'], 'GET') + t.match(res.headers['access-control-allow-methods'], 'POST') + t.match(res.headers['access-control-allow-methods'], 'OPTIONS') + t.end() + }) + }) + }) + + t.test('should reply with HTTP status code 200 to OPTIONS request', t => { + _boot([false, false, false, optsCors()], () => { + return request({ + method: 'options', + url: `http://localhost:8001/`, + body: '' + }, (err, res, body) => { + if (err) t.fail(err) + t.equal(res.statusCode, 200) + t.end() + }) + }) + }) + t.test('should emit *after-export* on successful requests', t => { _boot([], (args) => { const app = args[0]