@pkg-nec/http-server 14.1.1-pkgnec.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,192 @@
1
+ 'use strict';
2
+
3
+ var fs = require('fs'),
4
+ union = require('union'),
5
+ httpServerCore = require('./core'),
6
+ auth = require('basic-auth'),
7
+ httpProxy = require('http-proxy'),
8
+ corser = require('corser'),
9
+ secureCompare = require('secure-compare');
10
+
11
+ //
12
+ // Remark: backwards compatibility for previous
13
+ // case convention of HTTP
14
+ //
15
+ exports.HttpServer = exports.HTTPServer = HttpServer;
16
+
17
+ /**
18
+ * Returns a new instance of HttpServer with the
19
+ * specified `options`.
20
+ */
21
+ exports.createServer = function (options) {
22
+ return new HttpServer(options);
23
+ };
24
+
25
+ /**
26
+ * Constructor function for the HttpServer object
27
+ * which is responsible for serving static files along
28
+ * with other HTTP-related features.
29
+ */
30
+ function HttpServer(options) {
31
+ options = options || {};
32
+
33
+ if (options.root) {
34
+ this.root = options.root;
35
+ } else {
36
+ try {
37
+ // eslint-disable-next-line no-sync
38
+ fs.lstatSync('./public');
39
+ this.root = './public';
40
+ } catch (err) {
41
+ this.root = './';
42
+ }
43
+ }
44
+
45
+ this.headers = options.headers || {};
46
+ this.headers['Accept-Ranges'] = 'bytes';
47
+
48
+ this.cache = (
49
+ // eslint-disable-next-line no-nested-ternary
50
+ options.cache === undefined ? 3600 :
51
+ // -1 is a special case to turn off caching.
52
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control#Preventing_caching
53
+ options.cache === -1 ? 'no-cache, no-store, must-revalidate' :
54
+ options.cache // in seconds.
55
+ );
56
+ this.showDir = options.showDir !== 'false';
57
+ this.autoIndex = options.autoIndex !== 'false';
58
+ this.showDotfiles = options.showDotfiles;
59
+ this.gzip = options.gzip === true;
60
+ this.brotli = options.brotli === true;
61
+ if (options.ext) {
62
+ this.ext = options.ext === true
63
+ ? 'html'
64
+ : options.ext;
65
+ }
66
+ this.contentType = options.contentType ||
67
+ this.ext === 'html' ? 'text/html' : 'application/octet-stream';
68
+
69
+ var before = options.before ? options.before.slice() : [];
70
+
71
+ if (options.logFn) {
72
+ before.push(function (req, res) {
73
+ options.logFn(req, res);
74
+ res.emit('next');
75
+ });
76
+ }
77
+
78
+ if (options.username || options.password) {
79
+ before.push(function (req, res) {
80
+ var credentials = auth(req);
81
+
82
+ // We perform these outside the if to avoid short-circuiting and giving
83
+ // an attacker knowledge of whether the username is correct via a timing
84
+ // attack.
85
+ if (credentials) {
86
+ // if credentials is defined, name and pass are guaranteed to be string
87
+ // type
88
+ var usernameEqual = secureCompare(options.username.toString(), credentials.name);
89
+ var passwordEqual = secureCompare(options.password.toString(), credentials.pass);
90
+ if (usernameEqual && passwordEqual) {
91
+ return res.emit('next');
92
+ }
93
+ }
94
+
95
+ res.statusCode = 401;
96
+ res.setHeader('WWW-Authenticate', 'Basic realm=""');
97
+ res.end('Access denied');
98
+ });
99
+ }
100
+
101
+ if (options.cors) {
102
+ this.headers['Access-Control-Allow-Origin'] = '*';
103
+ this.headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Range';
104
+ if (options.corsHeaders) {
105
+ options.corsHeaders.split(/\s*,\s*/)
106
+ .forEach(function (h) { this.headers['Access-Control-Allow-Headers'] += ', ' + h; }, this);
107
+ }
108
+ before.push(corser.create(options.corsHeaders ? {
109
+ requestHeaders: this.headers['Access-Control-Allow-Headers'].split(/\s*,\s*/)
110
+ } : null));
111
+ }
112
+
113
+ if (options.robots) {
114
+ before.push(function (req, res) {
115
+ if (req.url === '/robots.txt') {
116
+ res.setHeader('Content-Type', 'text/plain');
117
+ var robots = options.robots === true
118
+ ? 'User-agent: *\nDisallow: /'
119
+ : options.robots.replace(/\\n/, '\n');
120
+
121
+ return res.end(robots);
122
+ }
123
+
124
+ res.emit('next');
125
+ });
126
+ }
127
+
128
+ before.push(httpServerCore({
129
+ root: this.root,
130
+ cache: this.cache,
131
+ showDir: this.showDir,
132
+ showDotfiles: this.showDotfiles,
133
+ autoIndex: this.autoIndex,
134
+ defaultExt: this.ext,
135
+ gzip: this.gzip,
136
+ brotli: this.brotli,
137
+ contentType: this.contentType,
138
+ mimetypes: options.mimetypes,
139
+ handleError: typeof options.proxy !== 'string'
140
+ }));
141
+
142
+ if (typeof options.proxy === 'string') {
143
+ var proxyOptions = options.proxyOptions || {};
144
+ var proxy = httpProxy.createProxyServer(proxyOptions);
145
+ before.push(function (req, res) {
146
+ proxy.web(req, res, {
147
+ target: options.proxy,
148
+ changeOrigin: true
149
+ }, function (err, req, res) {
150
+ if (options.logFn) {
151
+ options.logFn(req, res, {
152
+ message: err.message,
153
+ status: res.statusCode });
154
+ }
155
+ res.emit('next');
156
+ });
157
+ });
158
+ }
159
+
160
+ var serverOptions = {
161
+ before: before,
162
+ headers: this.headers,
163
+ onError: function (err, req, res) {
164
+ if (options.logFn) {
165
+ options.logFn(req, res, err);
166
+ }
167
+
168
+ res.end();
169
+ }
170
+ };
171
+
172
+ if (options.https) {
173
+ serverOptions.https = options.https;
174
+ }
175
+
176
+ this.server = serverOptions.https && serverOptions.https.passphrase
177
+ // if passphrase is set, shim must be used as union does not support
178
+ ? require('./shims/https-server-shim')(serverOptions)
179
+ : union.createServer(serverOptions);
180
+
181
+ if (options.timeout !== undefined) {
182
+ this.server.setTimeout(options.timeout);
183
+ }
184
+ }
185
+
186
+ HttpServer.prototype.listen = function () {
187
+ this.server.listen.apply(this.server, arguments);
188
+ };
189
+
190
+ HttpServer.prototype.close = function () {
191
+ return this.server.close();
192
+ };
@@ -0,0 +1,67 @@
1
+ /* eslint-disable no-process-env */
2
+ /* eslint-disable no-sync */
3
+ var https = require('https');
4
+ var fs = require('fs');
5
+ var core = require('union/lib/core');
6
+ var RoutingStream = require('union/lib/routing-stream');
7
+
8
+ module.exports = function (options) {
9
+ var isArray = Array.isArray(options.after);
10
+ var credentials;
11
+
12
+ if (!options) {
13
+ throw new Error('options is required to create a server');
14
+ }
15
+
16
+ function requestHandler(req, res) {
17
+ var routingStream = new RoutingStream({
18
+ before: options.before,
19
+ buffer: options.buffer,
20
+ after:
21
+ isArray &&
22
+ options.after.map(function (After) {
23
+ return new After();
24
+ }),
25
+ request: req,
26
+ response: res,
27
+ limit: options.limit,
28
+ headers: options.headers
29
+ });
30
+
31
+ routingStream.on('error', function (err) {
32
+ var fn = options.onError || core.errorHandler;
33
+ fn(err, routingStream, routingStream.target, function () {
34
+ routingStream.target.emit('next');
35
+ });
36
+ });
37
+
38
+ req.pipe(routingStream);
39
+ }
40
+
41
+ var serverOptions;
42
+
43
+ serverOptions = options.https;
44
+ if (!serverOptions.key || !serverOptions.cert) {
45
+ throw new Error(
46
+ 'Both options key and cert are required.'
47
+ );
48
+ }
49
+
50
+ credentials = {
51
+ key: fs.readFileSync(serverOptions.key),
52
+ cert: fs.readFileSync(serverOptions.cert),
53
+ passphrase: process.env.NODE_HTTP_SERVER_SSL_PASSPHRASE
54
+ };
55
+
56
+ if (serverOptions.ca) {
57
+ serverOptions.ca = !Array.isArray(serverOptions.ca)
58
+ ? [serverOptions.ca]
59
+ : serverOptions.ca;
60
+
61
+ credentials.ca = serverOptions.ca.map(function (ca) {
62
+ return fs.readFileSync(ca);
63
+ });
64
+ }
65
+
66
+ return https.createServer(credentials, requestHandler);
67
+ };
package/package.json ADDED
@@ -0,0 +1,122 @@
1
+ {
2
+ "name": "@pkg-nec/http-server",
3
+ "version": "14.1.1-pkgnec.0",
4
+ "description": "A simple zero-configuration command-line http server",
5
+ "main": "./lib/http-server",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/pkg-nec/http-server.git"
9
+ },
10
+ "keywords": [
11
+ "cli",
12
+ "command",
13
+ "static",
14
+ "http",
15
+ "https",
16
+ "http-server",
17
+ "https-server",
18
+ "server"
19
+ ],
20
+ "scripts": {
21
+ "start": "node ./bin/http-server",
22
+ "test": "tap --reporter=spec test/*.test.js",
23
+ "test-watch": "tap --reporter=spec --watch test/*.test.js"
24
+ },
25
+ "files": [
26
+ "lib",
27
+ "bin",
28
+ "doc"
29
+ ],
30
+ "man": "./doc/http-server.1",
31
+ "engines": {
32
+ "node": ">=12"
33
+ },
34
+ "contributors": [
35
+ {
36
+ "name": "Charlie Robbins",
37
+ "email": "charlie.robbins@gmail.com"
38
+ },
39
+ {
40
+ "name": "Marak Squires",
41
+ "email": "marak.squires@gmail.com"
42
+ },
43
+ {
44
+ "name": "Charlie McConnell",
45
+ "email": "charlie@charlieistheman.com"
46
+ },
47
+ {
48
+ "name": "Joshua Holbrook",
49
+ "email": "josh.holbrook@gmail.com"
50
+ },
51
+ {
52
+ "name": "Maciej Małecki",
53
+ "email": "maciej.malecki@notimplemented.org"
54
+ },
55
+ {
56
+ "name": "Matthew Bergman",
57
+ "email": "mzbphoto@gmail.com"
58
+ },
59
+ {
60
+ "name": "brad dunbar",
61
+ "email": "dunbarb2@gmail.com"
62
+ },
63
+ {
64
+ "name": "Dominic Tarr"
65
+ },
66
+ {
67
+ "name": "Travis Person",
68
+ "email": "travis.person@gmail.com"
69
+ },
70
+ {
71
+ "name": "Jinkwon Lee",
72
+ "email": "master@bdyne.net"
73
+ },
74
+ {
75
+ "name": "BigBlueHat",
76
+ "email": "byoung@bigbluehat.com"
77
+ },
78
+ {
79
+ "name": "Daniel Dalton",
80
+ "email": "daltond2@hawkmail.newpaltz.edu"
81
+ },
82
+ {
83
+ "name": "Jade Michael Thornton",
84
+ "email": "jademichael@jmthornton.net"
85
+ }
86
+ ],
87
+ "dependencies": {
88
+ "basic-auth": "^2.0.1",
89
+ "chalk": "^4.1.2",
90
+ "corser": "^2.0.1",
91
+ "he": "^1.2.0",
92
+ "html-encoding-sniffer": "^3.0.0",
93
+ "http-proxy": "^1.18.1",
94
+ "mime": "^1.6.0",
95
+ "minimist": "^1.2.6",
96
+ "opener": "^1.5.1",
97
+ "portfinder": "^1.0.28",
98
+ "secure-compare": "3.0.1",
99
+ "union": "~0.5.0",
100
+ "url-join": "^4.0.1"
101
+ },
102
+ "devDependencies": {
103
+ "eol": "^0.9.1",
104
+ "eslint": "^4.19.1",
105
+ "eslint-config-populist": "^4.2.0",
106
+ "express": "^4.17.1",
107
+ "request": "^2.88.2",
108
+ "tap": "^14.11.0"
109
+ },
110
+ "bugs": {
111
+ "url": "https://github.com/pkg-nec/http-server/issues"
112
+ },
113
+ "homepage": "https://github.com/pkg-nec/http-server#readme",
114
+ "license": "MIT",
115
+ "publishConfig": {
116
+ "access": "public"
117
+ },
118
+ "preferGlobal": true,
119
+ "bin": {
120
+ "http-server": "./bin/http-server"
121
+ }
122
+ }