Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ with the provided Dockerfile.
|`-b` or `--brotli`|When enabled it will serve `./public/some-file.js.br` in place of `./public/some-file.js` when a brotli compressed version of the file exists and the request accepts `br` encoding. If gzip is also enabled, it will try to serve brotli first. |`false`|
|`-e` or `--ext` |Default file extension if none supplied |`html` |
|`-s` or `--silent` |Suppress log messages from output | |
|`--coop` |Enable COOP via the `Cross-Origin-Opener-Policy` header | |
|`--cors` |Enable CORS via the `Access-Control-Allow-Origin` header | |
|`--cors` | Enable CORS via the `Access-Control-Allow-Origin: *` header. Optionally provide comma-separated values to add to `Access-Control-Allow-Headers` | |
|`-H` or `--header` |Add an extra response header (can be used several times) | |
|`-o [path]` |Open browser window after starting the server. Optionally provide a URL path to open. e.g.: -o /other/dir/ | |
Expand Down Expand Up @@ -138,6 +140,7 @@ This is what should be output if successful:
Starting up http-server, serving ./ through https

http-server settings:
COOP: disabled
CORS: disabled
Cache: 3600 seconds
Connection Timeout: 120 seconds
Expand Down
10 changes: 10 additions & 0 deletions bin/http-server
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ if (argv.h || argv.help) {
'',
' -e --ext Default file extension if none supplied [none]',
' -s --silent Suppress log messages from output',
' --coop[=mode] Enable COOP via the "Cross-Origin-Opener-Policy" header',
' Optionally provide COOP mode.',
' --content-type Default content type for unknown file types [application/octet-stream]',
' --cors[=headers] Enable CORS via the "Access-Control-Allow-Origin" header',
' When enabled, sets Access-Control-Allow-Origin to "*"',
Expand Down Expand Up @@ -192,6 +194,13 @@ function listen(port) {
}
}

if (argv.coop) {
options.coop = true;
if (typeof argv.coop === 'string') {
options.coopHeader = argv.coop;
}
}

if (websocket) {
if (!proxy) {
logger.warning(colors.yellow('WebSocket proxy will not be enabled because proxy is not enabled'));
Expand Down Expand Up @@ -272,6 +281,7 @@ function listen(port) {

logger.info([
chalk.yellow('\nhttp-server settings: '),
([chalk.yellow('COOP: '), argv.coop ? chalk.cyan(argv.coop) : chalk.red('disabled')].join('')),
([chalk.yellow('CORS: '), argv.cors ? chalk.cyan(argv.cors) : chalk.red('disabled')].join('')),
([chalk.yellow('Cache: '), argv.c ? (argv.c === '-1' ? chalk.red('disabled') : chalk.cyan(argv.c + ' seconds')) : chalk.cyan('3600 seconds')].join('')),
([chalk.yellow('Connection Timeout: '), argv.t === '0' ? chalk.red('disabled') : (argv.t ? chalk.cyan(argv.t + ' seconds') : chalk.cyan('120 seconds'))].join('')),
Expand Down
6 changes: 6 additions & 0 deletions doc/http-server.1
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ Default file extension is none is provided.
.BI \-s ", " \-\-silent
Suppress log messages from output.

.TP
.BI \-\-coop " " [\fIMODE\fR]
Enable COOP via the "Cross-Origin-Opener-Policy" header and sets
the "Cross-Origin-Embedder-Policy" header to "require-corp".
Optionally provide COOP mode which defaults to "same-origin".

.TP
.BI \-\-cors " " [\fIHEADERS\fR]
Enable CORS by setting "Access-Control-Allow-Origin" to "*".
Expand Down
1 change: 1 addition & 0 deletions lib/core/aliases.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"hidePermissions": ["hidePermissions", "hidepermissions", "hide-permissions"],
"si": [ "si", "index" ],
"handleError": [ "handleError", "handleerror" ],
"coop": [ "coop", "COOP" ],
"cors": [ "cors", "CORS" ],
"headers": [ "H", "header", "headers" ],
"contentType": [ "contentType", "contenttype", "content-type" ],
Expand Down
1 change: 1 addition & 0 deletions lib/core/defaults.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"hidePermissions": false,
"si": false,
"cache": "max-age=3600",
"coop": false,
"cors": false,
"gzip": true,
"brotli": false,
Expand Down
8 changes: 8 additions & 0 deletions lib/core/opts.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,14 @@ module.exports = (opts) => {
return false;
});

aliases.coop.forEach((k) => {
if (isDeclared(k) && opts[k]) {
handleOptionsMethod = true;
headers['Cross-Origin-Opener-Policy'] = 'same-origin';
headers['Cross-Origin-Embedder-Policy'] = 'require-corp';
}
});

aliases.cors.forEach((k) => {
if (isDeclared(k) && opts[k]) {
handleOptionsMethod = true;
Expand Down
5 changes: 5 additions & 0 deletions lib/http-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ function HttpServer(options) {
});
}

if (options.coop) {
this.headers['Cross-Origin-Opener-Policy'] = options.coopHeader || 'same-origin';
this.headers['Cross-Origin-Embedder-Policy'] = 'require-corp';
}

// CORS configuration:
// --cors enables CORS by setting Access-Control-Allow-Origin to '*'
// --cors=header1,header2 also adds custom headers to Access-Control-Allow-Headers
Expand Down
118 changes: 118 additions & 0 deletions test/coop.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
'use strict';

const test = require('tap').test;
const server = require('../lib/core');
const http = require('http');
const path = require('path');
const request = require('request');

const root = path.join(__dirname, 'public');

test('coop defaults to false', (t) => {
t.plan(4);

const httpServer = http.createServer(
server({
root,
autoIndex: true,
defaultExt: 'html',
})
);

httpServer.listen(() => {
const port = httpServer.address().port;
const uri = `http://localhost:${port}/subdir/index.html`;

request.get({ uri }, (err, res) => {
t.error(err);
t.equal(res.statusCode, 200);
t.type(res.headers['cross-origin-opener-policy'], 'undefined');
t.type(res.headers['cross-origin-embedder-policy'], 'undefined');
});
});
t.once('end', () => {
httpServer.close();
});
});

test('coop set to false', (t) => {
t.plan(4);

const httpServer = http.createServer(
server({
root,
coop: false,
autoIndex: true,
defaultExt: 'html',
})
);

httpServer.listen(() => {
const port = httpServer.address().port;
const uri = `http://localhost:${port}/subdir/index.html`;

request.get({ uri }, (err, res) => {
t.error(err);
t.equal(res.statusCode, 200);
t.type(res.headers['cross-origin-opener-policy'], 'undefined');
t.type(res.headers['cross-origin-embedder-policy'], 'undefined');
});
});
t.once('end', () => {
httpServer.close();
});
});

test('coop set to true', (t) => {
t.plan(4);

const httpServer = http.createServer(
server({
root,
coop: true,
autoIndex: true,
defaultExt: 'html',
})
);

httpServer.listen(() => {
const port = httpServer.address().port;
const uri = `http://localhost:${port}/subdir/index.html`;
request.get({ uri }, (err, res) => {
t.error(err);
t.equal(res.statusCode, 200);
t.equal(res.headers['cross-origin-opener-policy'], 'same-origin');
t.equal(res.headers['cross-origin-embedder-policy'], 'require-corp');
});
});
t.once('end', () => {
httpServer.close();
});
});

test('COOP set to true', (t) => {
t.plan(4);

const httpServer = http.createServer(
server({
root,
COOP: true,
autoIndex: true,
defaultExt: 'html',
})
);

httpServer.listen(() => {
const port = httpServer.address().port;
const uri = `http://localhost:${port}/subdir/index.html`;
request.get({ uri }, (err, res) => {
t.error(err);
t.equal(res.statusCode, 200);
t.equal(res.headers['cross-origin-opener-policy'], 'same-origin');
t.equal(res.headers['cross-origin-embedder-policy'], 'require-corp');
});
});
t.once('end', () => {
httpServer.close();
});
});
3 changes: 3 additions & 0 deletions test/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ test('http-server main', (t) => {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true'
},
coop: true,
cors: true,
corsHeaders: 'X-Test',
ext: true,
Expand Down Expand Up @@ -64,6 +65,8 @@ test('http-server main', (t) => {
// Custom headers
t.equal(res.headers['access-control-allow-origin'], '*');
t.equal(res.headers['access-control-allow-credentials'], 'true');
t.equal(res.headers['cross-origin-opener-policy'], 'same-origin');
t.equal(res.headers['cross-origin-embedder-policy'], 'require-corp');
}).catch(err => t.fail(err.toString())),

// Get robots
Expand Down
Loading