Skip to content
Open
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
84 changes: 66 additions & 18 deletions bin/http-server
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#!/usr/bin/env node

'use strict';

var chalk = require('chalk'),
os = require('os'),
httpServer = require('../lib/http-server'),
Expand All @@ -24,7 +23,7 @@ if (argv.h || argv.help) {
'usage: http-server [path] [options]',
'',
'options:',
' -p --port Port to use. If 0, look for open port. [8080]',
' -p --port Port to use. If 0, look for open port. [8080]. If --https-redirect, http and (main) https port [8080,443]',
' -a Address to use [0.0.0.0]',
' -d Show directory listings [true]',
' -i Display autoIndex [true]',
Expand All @@ -44,17 +43,18 @@ if (argv.h || argv.help) {
' -U --utc Use UTC time format in log messages.',
' --log-ip Enable logging of the client\'s IP address',
'',
' -P --proxy Fallback proxy if the request cannot be resolved. e.g.: http://someurl.com',
' --proxy-options Pass options to proxy using nested dotted objects. e.g.: --proxy-options.secure false',
' -P --proxy Fallback proxy if the request cannot be resolved. e.g.: http://someurl.com',
' --proxy-options Pass options to proxy using nested dotted objects. e.g.: --proxy-options.secure false',
' -R --https-redirect Auto redirects http -> https',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that -R properly captures the option, how do you feel about using only --https-redirect?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heyy thanks so much for the review ^^

And well, I don't have a problem removing it.. I just thought that it's a somewhat much requested and often used feature and it'd be nice to have a shortcut for Redirection.. your call.. ^^

'',
' --username Username for basic authentication [none]',
' Can also be specified with the env variable NODE_HTTP_SERVER_USERNAME',
' --password Password for basic authentication [none]',
' Can also be specified with the env variable NODE_HTTP_SERVER_PASSWORD',
'',
' -S --tls --ssl Enable secure request serving with TLS/SSL (HTTPS)',
' -C --cert Path to TLS cert file (default: cert.pem)',
' -K --key Path to TLS key file (default: key.pem)',
' -S --tls --ssl Enable secure request serving with TLS/SSL (HTTPS)',
' -C --cert Path to TLS cert file (default: cert.pem)',
' -K --key Path to TLS key file (default: key.pem)',
'',
' -r --robots Respond to /robots.txt [User-agent: *\\nDisallow: /]',
' --no-dotfiles Do not show dotfiles',
Expand All @@ -73,6 +73,7 @@ var port = argv.p || argv.port || parseInt(process.env.PORT, 10),
proxyOptions = argv['proxy-options'],
utc = argv.U || argv.utc,
version = argv.v || argv.version,
redirect = !!argv.R || !!argv['https-redirect'],
logger;

var proxyOptionsBooleanProps = [
Expand Down Expand Up @@ -125,18 +126,56 @@ if (version) {
process.exit();
}

if (!port) {
portfinder.basePort = 8080;
portfinder.getPort(function (err, port) {
if (err) { throw err; }
listen(port);
});
if (port === true) {
logger.info(chalk.red('Error: --port needs a value'));
process.exit(1);
return;
}

if (tls && redirect) {
var ports = [];
if (!port) {
ports = [8080,443];
}
else if (typeof port === 'string') {
ports = (port.toString() || '').split(',').map(function (s) { return parseInt(s, 10) });
}
else {
logger.info(chalk.red('Error: Cannot parse "--port ' + port + '" of type ' + typeof port + '. Port has to be in the format [httpPort,httpsPort]\nExample: --port 8080,443'));
process.exit(1);
}

if (ports.length === 2) {
if (isNaN(ports[0]) || isNaN(ports[1])) {
logger.info(chalk.red('Error parsing "--port ' + port + '". [' + ports + '] is not of type [number,number]'));
process.exit(1);
}
}
else {
logger.info(chalk.red('Error: Cannot parse "--port ' + port + '"\nExample: --port 8080,443'));
process.exit(1);
}

listen(ports[1]);
listen(ports[0], ports[1]);
}
else if (!tls && redirect) {
logger.info(chalk.red('Error: Can\'t redirect to https when the main server runs on http!'));
}
else {
listen(port);
if (!port) {
portfinder.basePort = 8080;
portfinder.getPort(function (err, port) {
if (err) { throw err; }
listen(port);
});
}
else {
listen(port);
}
}

function listen(port) {
function listen(port, redirectPort) {
var options = {
root: argv._[0],
cache: argv.c,
Expand All @@ -150,12 +189,15 @@ function listen(port) {
logFn: logger.request,
proxy: proxy,
proxyOptions: proxyOptions,
httpsPort: redirectPort,
showDotfiles: argv.dotfiles,
mimetypes: argv.mimetypes,
username: argv.username || process.env.NODE_HTTP_SERVER_USERNAME,
password: argv.password || process.env.NODE_HTTP_SERVER_PASSWORD
};

var isTLSServer = (tls && !redirectPort);

if (argv.cors) {
options.cors = true;
if (typeof argv.cors === 'string') {
Expand All @@ -173,7 +215,7 @@ function listen(port) {
}
}

if (tls) {
if (isTLSServer) {
options.https = {
cert: argv.C || argv.cert || 'cert.pem',
key: argv.K || argv.key || 'key.pem',
Expand All @@ -197,12 +239,14 @@ function listen(port) {

var server = httpServer.createServer(options);
server.listen(port, host, function () {
var protocol = tls ? 'https://' : 'http://';

var protocol = isTLSServer ? 'https://' : 'http://';

logger.info([
chalk.yellow('Starting up http-server, serving '),
chalk.cyan(server.root),
tls ? (chalk.yellow(' through') + chalk.cyan(' https')) : ''
isTLSServer ? (chalk.yellow(' through') + chalk.cyan(' https')) : '',
chalk.yellow('\nAvailable on:')
].join(''));

logger.info([chalk.yellow('\nhttp-server version: '), chalk.cyan(require('../package.json').version)].join(''));
Expand Down Expand Up @@ -242,6 +286,10 @@ function listen(port) {
}
}

if (redirectPort) {
logger.info('[Redirect listener]');
}

logger.info('Hit CTRL-C to stop the server');
if (argv.o) {
const openHost = host === '0.0.0.0' ? '127.0.0.1' : host;
Expand Down
16 changes: 13 additions & 3 deletions lib/http-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ function HttpServer(options) {
this.cache = (
// eslint-disable-next-line no-nested-ternary
options.cache === undefined ? 3600 :
// -1 is a special case to turn off caching.
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Preventing_caching
// -1 is a special case to turn off caching.
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Preventing_caching
options.cache === -1 ? 'no-cache, no-store, must-revalidate' :
options.cache // in seconds.
);
Expand All @@ -68,6 +68,15 @@ function HttpServer(options) {

var before = options.before ? options.before.slice() : [];

if (options.httpsPort) {
before.push(function (req, res) {
var hostname = req.headers.host.match(/:/g) ? req.headers.host.slice(0, req.headers.host.indexOf(':')) : req.headers.host;
var httpsUrl = 'https://' + hostname + ':' + options.httpsPort + req.url;
res.writeHead(301, { Location: httpsUrl });
res.end();
});
}

if (options.logFn) {
before.push(function (req, res) {
options.logFn(req, res);
Expand Down Expand Up @@ -150,7 +159,8 @@ function HttpServer(options) {
if (options.logFn) {
options.logFn(req, res, {
message: err.message,
status: res.statusCode });
status: res.statusCode
});
}
res.emit('next');
});
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@
{
"name": "Jade Michael Thornton",
"email": "[email protected]"
},
{
"name": "Henrik Storch",
"email": "[email protected]"
}
],
"dependencies": {
Expand Down