You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 7-8.RSVP
Socket
Socket
Sign inDemoInstall

http-server

Package Overview
Dependencies
Maintainers
3
Versions
49
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 13.0.2 to 14.0.0

lib/core/show-dir/last-modified-to-string.js

234

lib/core/index.js

@@ -8,2 +8,4 @@ #! /usr/bin/env node

const url = require('url');
const { Readable } = require('stream');
const buffer = require('buffer');
const mime = require('mime');

@@ -16,2 +18,3 @@ const urlJoin = require('url-join');

const optsParser = require('./opts');
const htmlEncodingSniffer = require('html-encoding-sniffer');

@@ -33,5 +36,10 @@ let httpServerCore = null;

return process.platform === 'win32'
? normalized.replace(/\\/g, '/') : normalized;
? normalized.replace(/\\/g, '/') : normalized;
}
const nonUrlSafeCharsRgx = /[\x00-\x1F\x20\x7F-\uFFFF]+/g;
function ensureUriEncoded(text) {
return text
return String(text).replace(nonUrlSafeCharsRgx, encodeURIComponent);
}

@@ -44,5 +52,5 @@ // Check to see if we should try to compress a file with gzip.

headers['accept-encoding']
.split(',')
.some(el => ['*', 'compress', 'gzip', 'deflate'].indexOf(el.trim()) !== -1)
;
.split(',')
.some(el => ['*', 'compress', 'gzip', 'deflate'].indexOf(el.trim()) !== -1)
;
}

@@ -62,3 +70,3 @@

const stream = fs.createReadStream(gzipped, { start: 0, end: 1 });
let buffer = Buffer('');
let buffer = Buffer.from('');
let hasBeenCalled = false;

@@ -167,5 +175,6 @@

if (opts.weakCompare && clientEtag !== serverEtag
&& clientEtag !== `W/${serverEtag}` && `W/${clientEtag}` !== serverEtag) {
&& clientEtag !== `W/${serverEtag}` && `W/${clientEtag}` !== serverEtag) {
return false;
} else if (!opts.weakCompare && (clientEtag !== serverEtag || clientEtag.indexOf('W/') === 0)) {
}
if (!opts.weakCompare && (clientEtag !== serverEtag || clientEtag.indexOf('W/') === 0)) {
return false;

@@ -231,3 +240,2 @@ }

let contentType = mime.lookup(file, defaultType);
let charSet;
const range = (req.headers && req.headers.range);

@@ -239,4 +247,13 @@ const lastModified = (new Date(stat.mtime)).toUTCString();

if (contentType && isTextFile(contentType)) {
// Assume text types are utf8
contentType += '; charset=UTF-8';
if (stat.size < buffer.constants.MAX_LENGTH) {
const bytes = fs.readFileSync(file);
const sniffedEncoding = htmlEncodingSniffer(bytes, {
defaultEncoding: 'UTF-8'
});
contentType += `; charset=${sniffedEncoding}`;
stream = Readable.from(bytes)
} else {
// Assume text types are utf8
contentType += '; charset=UTF-8';
}
}

@@ -323,3 +340,6 @@

stream = fs.createReadStream(file);
// stream may already have been assigned during encoding sniffing.
if (stream === null) {
stream = fs.createReadStream(file);
}

@@ -330,2 +350,5 @@ stream.pipe(res);

});
stream.on('close', () => {
stream.destroy();
})
}

@@ -335,70 +358,79 @@

function statFile() {
fs.stat(file, (err, stat) => {
if (err && (err.code === 'ENOENT' || err.code === 'ENOTDIR')) {
if (req.statusCode === 404) {
// This means we're already trying ./404.html and can not find it.
// So send plain text response with 404 status code
status[404](res, next);
} else if (!path.extname(parsed.pathname).length && defaultExt) {
// If there is no file extension in the path and we have a default
// extension try filename and default extension combination before rendering 404.html.
middleware({
url: `${parsed.pathname}.${defaultExt}${(parsed.search) ? parsed.search : ''}`,
headers: req.headers,
}, res, next);
} else {
// Try to serve default ./404.html
middleware({
url: (handleError ? `/${path.join(baseDir, `404.${defaultExt}`)}` : req.url),
headers: req.headers,
statusCode: 404,
}, res, next);
}
} else if (err) {
status[500](res, next, { error: err });
} else if (stat.isDirectory()) {
if (!autoIndex && !opts.showDir) {
status[404](res, next);
return;
}
try {
fs.stat(file, (err, stat) => {
if (err && (err.code === 'ENOENT' || err.code === 'ENOTDIR')) {
if (req.statusCode === 404) {
// This means we're already trying ./404.html and can not find it.
// So send plain text response with 404 status code
status[404](res, next);
} else if (!path.extname(parsed.pathname).length && defaultExt) {
// If there is no file extension in the path and we have a default
// extension try filename and default extension combination before rendering 404.html.
middleware({
url: `${parsed.pathname}.${defaultExt}${(parsed.search) ? parsed.search : ''}`,
headers: req.headers,
}, res, next);
} else {
// Try to serve default ./404.html
const rawUrl = (handleError ? `/${path.join(baseDir, `404.${defaultExt}`)}` : req.url);
const encodedUrl = ensureUriEncoded(rawUrl);
middleware({
url: encodedUrl,
headers: req.headers,
statusCode: 404,
}, res, next);
}
} else if (err) {
status[500](res, next, { error: err });
} else if (stat.isDirectory()) {
if (!autoIndex && !opts.showDir) {
status[404](res, next);
return;
}
// 302 to / if necessary
if (!pathname.match(/\/$/)) {
res.statusCode = 302;
const q = parsed.query ? `?${parsed.query}` : '';
res.setHeader('location', `${parsed.pathname}/${q}`);
res.end();
return;
}
// 302 to / if necessary
if (!pathname.match(/\/$/)) {
res.statusCode = 302;
const q = parsed.query ? `?${parsed.query}` : '';
res.setHeader(
'location',
ensureUriEncoded(`${parsed.pathname}/${q}`)
);
res.end();
return;
}
if (autoIndex) {
middleware({
url: urlJoin(
encodeURIComponent(pathname),
`/index.${defaultExt}`
),
headers: req.headers,
}, res, (autoIndexError) => {
if (autoIndexError) {
status[500](res, next, { error: autoIndexError });
return;
}
if (opts.showDir) {
showDir(opts, stat)(req, res);
return;
}
if (autoIndex) {
middleware({
url: urlJoin(
encodeURIComponent(pathname),
`/index.${defaultExt}`
),
headers: req.headers,
}, res, (autoIndexError) => {
if (autoIndexError) {
status[500](res, next, { error: autoIndexError });
return;
}
if (opts.showDir) {
showDir(opts, stat)(req, res);
return;
}
status[403](res, next);
});
return;
}
status[403](res, next);
});
return;
}
if (opts.showDir) {
showDir(opts, stat)(req, res);
if (opts.showDir) {
showDir(opts, stat)(req, res);
}
} else {
serve(stat);
}
} else {
serve(stat);
}
});
});
} catch (err) {
status[500](res, next, { error: err.message });
}
}

@@ -412,16 +444,20 @@

function tryServeWithGzip() {
fs.stat(gzippedFile, (err, stat) => {
if (!err && stat.isFile()) {
hasGzipId12(gzippedFile, (gzipErr, isGzip) => {
if (!gzipErr && isGzip) {
file = gzippedFile;
serve(stat);
} else {
statFile();
}
});
} else {
statFile();
}
});
try {
fs.stat(gzippedFile, (err, stat) => {
if (!err && stat.isFile()) {
hasGzipId12(gzippedFile, (gzipErr, isGzip) => {
if (!gzipErr && isGzip) {
file = gzippedFile;
serve(stat);
} else {
statFile();
}
});
} else {
statFile();
}
});
} catch (err) {
status[500](res, next, { error: err.message });
}
}

@@ -431,12 +467,16 @@

function tryServeWithBrotli(shouldTryGzip) {
fs.stat(brotliFile, (err, stat) => {
if (!err && stat.isFile()) {
file = brotliFile;
serve(stat);
} else if (shouldTryGzip) {
tryServeWithGzip();
} else {
statFile();
}
});
try {
fs.stat(brotliFile, (err, stat) => {
if (!err && stat.isFile()) {
file = brotliFile;
serve(stat);
} else if (shouldTryGzip) {
tryServeWithGzip();
} else {
statFile();
}
});
} catch (err) {
status[500](res, next, { error: err.message });
}
}

@@ -443,0 +483,0 @@

@@ -121,3 +121,3 @@ 'use strict';

aliases.cors.forEach((k) => {
if (isDeclared(k) && k) {
if (isDeclared(k) && opts[k]) {
handleOptionsMethod = true;

@@ -124,0 +124,0 @@ headers['Access-Control-Allow-Origin'] = '*';

'use strict';
const styles = require('./styles');
const lastModifiedToString = require('./last-modified-to-string');
const permsToString = require('./perms-to-string');

@@ -98,3 +99,3 @@ const sizeToString = require('./size-to-string');

const isDir = file[1].isDirectory && file[1].isDirectory();
let href = `${parsed.pathname.replace(/\/$/, '')}/${encodeURIComponent(file[0])}`;
let href = `./${encodeURIComponent(file[0])}`;

@@ -118,2 +119,3 @@ // append trailing slash and query for dir entry

html +=
`<td class="last-modified">${lastModifiedToString(file[1])}</td>` +
`<td class="file-size"><code>${sizeToString(file[1], humanReadable, si)}</code></td>` +

@@ -120,0 +122,0 @@ `<td class="display-name"><a href="${href}">${displayName}</a></td>` +

'use strict';
var fs = require('fs'),
union = require('union'),
httpServerCore = require('./core'),
auth = require('basic-auth'),
httpProxy = require('http-proxy'),
corser = require('corser'),
path = require('path'),
secureCompare = require('secure-compare');
union = require('union'),
httpServerCore = require('./core'),
auth = require('basic-auth'),
httpProxy = require('http-proxy'),
corser = require('corser'),
secureCompare = require('secure-compare');

@@ -36,9 +35,8 @@ //

this.root = options.root;
}
else {
} else {
try {
// eslint-disable-next-line no-sync
fs.lstatSync('./public');
this.root = './public';
}
catch (err) {
} catch (err) {
this.root = './';

@@ -52,7 +50,8 @@ }

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
options.cache === -1 ? 'no-cache, no-store, must-revalidate' :
options.cache // in seconds.
options.cache === -1 ? 'no-cache, no-store, must-revalidate' :
options.cache // in seconds.
);

@@ -109,3 +108,3 @@ this.showDir = options.showDir !== 'false';

options.corsHeaders.split(/\s*,\s*/)
.forEach(function (h) { this.headers['Access-Control-Allow-Headers'] += ', ' + h; }, this);
.forEach(function (h) { this.headers['Access-Control-Allow-Headers'] += ', ' + h; }, this);
}

@@ -147,3 +146,4 @@ before.push(corser.create(options.corsHeaders ? {

if (typeof options.proxy === 'string') {
var proxy = httpProxy.createProxyServer({});
var proxyOptions = options.proxyOptions || {};
var proxy = httpProxy.createProxyServer(proxyOptions);
before.push(function (req, res) {

@@ -153,3 +153,3 @@ proxy.web(req, res, {

changeOrigin: true
}, function (err, req, res, target) {
}, function (err, req, res) {
if (options.logFn) {

@@ -181,3 +181,7 @@ options.logFn(req, res, {

this.server = union.createServer(serverOptions);
this.server = serverOptions.https && serverOptions.https.passphrase
// if passphrase is set, shim must be used as union does not support
? require('./shims/https-server-shim')(serverOptions)
: union.createServer(serverOptions);
if (options.timeout !== undefined) {

@@ -184,0 +188,0 @@ this.server.setTimeout(options.timeout);

{
"name": "http-server",
"version": "13.0.2",
"version": "14.0.0",
"description": "A simple zero-configuration command-line http server",

@@ -32,3 +32,3 @@ "main": "./lib/http-server",

"engines": {
"node": ">=6"
"node": ">=12"
},

@@ -89,20 +89,21 @@ "contributors": [

"dependencies": {
"basic-auth": "^1.0.3",
"basic-auth": "^2.0.1",
"colors": "^1.4.0",
"corser": "^2.0.1",
"he": "^1.1.0",
"http-proxy": "^1.18.0",
"he": "^1.2.0",
"html-encoding-sniffer": "^3.0.0",
"http-proxy": "^1.18.1",
"mime": "^1.6.0",
"minimist": "^1.2.5",
"opener": "^1.5.1",
"portfinder": "^1.0.25",
"portfinder": "^1.0.28",
"secure-compare": "3.0.1",
"union": "~0.5.0",
"url-join": "^2.0.5"
"url-join": "^4.0.1"
},
"devDependencies": {
"common-style": "^3.0.0",
"eol": "^0.9.1",
"express": "^4.16.3",
"mkdirp": "^0.5.0",
"eslint": "^4.19.1",
"eslint-config-populist": "^4.2.0",
"express": "^4.17.1",
"request": "^2.88.2",

@@ -109,0 +110,0 @@ "tap": "^14.11.0"

@@ -61,5 +61,6 @@ [![GitHub Workflow Status (master)](https://img.shields.io/github/workflow/status/http-party/http-server/Node.js%20CI/master?style=flat-square)](https://github.com/http-party/http-server/actions)

|`-P` or `--proxy` |Proxies all requests which can't be resolved locally to the given url. e.g.: -P http://someurl.com | |
|`--proxy-options` |Pass proxy [options](https://github.com/http-party/node-http-proxy#options) using nested dotted objects. e.g.: --proxy-options.secure false |
|`--username` |Username for basic authentication | |
|`--password` |Password for basic authentication | |
|`-S` or `--ssl` |Enable https.| |
|`-S`, `--tls` or `--ssl` |Enable secure request serving with TLS/SSL (HTTPS)|`false`|
|`-C` or `--cert` |Path to ssl cert file |`cert.pem` |

@@ -106,2 +107,11 @@ |`-K` or `--key` |Path to ssl key file |`key.pem` |

If you wish to use a passphrase with your private key you can include one in the openssl command via the -passout parameter (using password of foobar)
e.g.
`openssl req -newkey rsa:2048 -passout pass:foobar -keyout key.pem -x509 -days 365 -out cert.pem`
For security reasons, the passphrase will only be read from the `NODE_HTTP_SERVER_SSL_PASSPHRASE` environment variable.
This is what should be output if successful:

@@ -108,0 +118,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc