Skip to content

Commit fe91590

Browse files
MaximSaganjesseditsonJesse Ditsonmax.saganKernelDeimos
authored
feat: add --base-dir to cli options to specify base path (#837)
* Add baseDir option, add --baseDir flag to cli options to specify base path * add path to logged URLs * Address feedback from @thornjad, add --base-dir flag * base-dir tests --------- Co-authored-by: Jesse Ditson <[email protected]> Co-authored-by: Jesse Ditson <[email protected]> Co-authored-by: max.sagan <[email protected]> Co-authored-by: Eric Dubé <[email protected]>
1 parent 3b86caa commit fe91590

File tree

4 files changed

+43
-4
lines changed

4 files changed

+43
-4
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ with the provided Dockerfile.
6262
| ------------- |-------------|-------------|
6363
|`-p` or `--port` |Port to use. Use `-p 0` to look for an open port, starting at 8080. It will also read from `process.env.PORT`. |8080 |
6464
|`-a` |Address to use |0.0.0.0|
65+
|`--base-dir` | Base path to serve files from | `/` |
6566
|`-d` |Show directory listings |`true` |
6667
|`-i` | Display autoIndex | `true` |
6768
|`-g` or `--gzip` |When enabled it will serve `./public/some-file.js.gz` in place of `./public/some-file.js` when a gzipped version of the file exists and the request accepts gzip encoding. If brotli is also enabled, it will try to serve brotli first.|`false`|

bin/http-server

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ if (argv.h || argv.help) {
2828
' -p --port Port to use. If 0, look for open port. [8080]',
2929
' -a Address to use [0.0.0.0] or [::]',
3030
' -d Show directory listings [true]',
31+
' --base-dir Base directory to serve files from [/]',
3132
' -i Display autoIndex [true]',
3233
' -g --gzip Serve gzip files when possible [false]',
3334
' -b --brotli Serve brotli files when possible [false]',
@@ -77,6 +78,7 @@ var port = argv.p || argv.port || parseInt(process.env.PORT, 10),
7778
proxyOptions = argv['proxy-options'],
7879
utc = argv.U || argv.utc,
7980
version = argv.v || argv.version,
81+
baseDir = argv['base-dir'],
8082
logger;
8183

8284
var proxyOptionsBooleanProps = [
@@ -146,6 +148,7 @@ function listen(port) {
146148
cache: argv.c,
147149
timeout: argv.t,
148150
showDir: argv.d,
151+
baseDir: baseDir,
149152
autoIndex: argv.i,
150153
gzip: argv.g || argv.gzip,
151154
brotli: argv.b || argv.brotli,
@@ -220,7 +223,8 @@ function listen(port) {
220223

221224
var server = httpServer.createServer(options);
222225
server.listen(port, host, function () {
223-
var protocol = tls ? 'https://' : 'http://';
226+
var protocol = tls ? 'https://' : 'http://',
227+
path = baseDir ? '/' + baseDir.replace(/^\//, '') : '';
224228

225229
logger.info([
226230
chalk.yellow('Starting up http-server, serving '),
@@ -239,7 +243,8 @@ function listen(port) {
239243
([chalk.yellow('AutoIndex: '), argv.i ? chalk.red('not visible') : chalk.cyan('visible')].join('')),
240244
([chalk.yellow('Serve GZIP Files: '), argv.g || argv.gzip ? chalk.cyan('true') : chalk.red('false')].join('')),
241245
([chalk.yellow('Serve Brotli Files: '), argv.b || argv.brotli ? chalk.cyan('true') : chalk.red('false')].join('')),
242-
([chalk.yellow('Default File Extension: '), argv.e ? chalk.cyan(argv.e) : (argv.ext ? chalk.cyan(argv.ext) : chalk.red('none'))].join(''))
246+
([chalk.yellow('Default File Extension: '), argv.e ? chalk.cyan(argv.e) : (argv.ext ? chalk.cyan(argv.ext) : chalk.red('none'))].join('')),
247+
([chalk.yellow('Base directory: '), baseDir ? chalk.cyan(baseDir) : chalk.cyan('/')].join(''))
243248
].join('\n'));
244249

245250
if (options.headers) {
@@ -252,13 +257,14 @@ function listen(port) {
252257

253258
logger.info(chalk.yellow('\nAvailable on:'));
254259

260+
255261
if (argv.a && (host !== '::' || host !== '0.0.0.0')) {
256-
logger.info(` ${protocol}${host}:${chalk.green(port.toString())}`);
262+
logger.info(` ${protocol}${host}:${chalk.green(port.toString())}${path}`);
257263
} else {
258264
Object.keys(ifaces).forEach(function (dev) {
259265
ifaces[dev].forEach(function (details) {
260266
if (details.family === 'IPv4') {
261-
logger.info((' ' + protocol + details.address + ':' + chalk.green(port.toString())));
267+
logger.info((' ' + protocol + details.address + ':' + chalk.green(port.toString()) + path));
262268
}
263269
if (details.family === 'IPv6' && !details.address.startsWith("fe80") ) { // Ignoring Ipv6-Link Local addresses
264270
logger.info((' ' + protocol + details.address + ':' + chalk.green(port.toString())));

lib/http-server.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ function HttpServer(options) {
127127

128128
before.push(httpServerCore({
129129
root: this.root,
130+
baseDir: options.baseDir,
130131
cache: this.cache,
131132
showDir: this.showDir,
132133
showDotfiles: this.showDotfiles,

test/main.test.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,37 @@ test('http-server main', (t) => {
291291
}
292292
});
293293
}),
294+
295+
new Promise((resolve) => {
296+
const server = httpServer.createServer({
297+
root,
298+
baseDir: '/test'
299+
});
300+
301+
server.listen(8084, async () => {
302+
try {
303+
await Promise.all([
304+
// should serve files at the specified baseDir
305+
requestAsync("http://localhost:8084/test/file").then(async (res) => {
306+
t.equal(res.statusCode, 200);
307+
const fileData = await fsReadFile(path.join(root, 'file'), 'utf8');
308+
t.equal(res.body.trim(), fileData.trim());
309+
}).catch(err => t.fail(err.toString())),
310+
311+
// should not serve files at the root
312+
requestAsync("http://localhost:8084/file").then((res) => {
313+
t.equal(res.statusCode, 403);
314+
t.equal(res.body, '');
315+
}).catch(err => t.fail(err.toString())),
316+
]);
317+
} catch (err) {
318+
t.fail(err.toString());
319+
} finally {
320+
server.close();
321+
resolve();
322+
}
323+
});
324+
}),
294325
]).then(() => t.end())
295326
.catch(err => {
296327
t.fail(err.toString());

0 commit comments

Comments
 (0)