@warren-bank/hls-proxy 0.18.1 → 0.19.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.
- package/README.md +91 -8
- package/hls-proxy/bin/hlsd.js +3 -1
- package/hls-proxy/bin/lib/help.js +34 -31
- package/hls-proxy/bin/lib/process_argv.js +49 -35
- package/hls-proxy/proxy.js +22 -5
- package/hls-proxy/servers/lib/LAN_IPs.js +49 -1
- package/hls-proxy/servers/start_http.js +6 -14
- package/hls-proxy/servers/start_https.js +19 -21
- package/package.json +3 -2
- package/hls-proxy/bin/lib/grep_argv.js +0 -91
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
### [
|
|
1
|
+
### [_HLS Proxy_](https://github.com/warren-bank/HLS-Proxy) : HTTP Live Streaming Proxy
|
|
2
2
|
|
|
3
3
|
#### Basic Functionality:
|
|
4
4
|
|
|
@@ -33,6 +33,58 @@
|
|
|
33
33
|
|
|
34
34
|
- - - -
|
|
35
35
|
|
|
36
|
+
#### URL Format:
|
|
37
|
+
|
|
38
|
+
* [example Javascript]: construction of URL to _HLS Proxy_ for video stream
|
|
39
|
+
```javascript
|
|
40
|
+
{
|
|
41
|
+
const proxy_url = 'http://127.0.0.1:8080'
|
|
42
|
+
const video_url = 'https://example.com/video/master.m3u8'
|
|
43
|
+
const file_extension = '.m3u8'
|
|
44
|
+
|
|
45
|
+
const hls_proxy_url = `${proxy_url}/${ btoa(video_url) }${file_extension}`
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
* [example Javascript]: construction of URL to _HLS Proxy_ for video stream w/ "Referer" request header
|
|
49
|
+
```javascript
|
|
50
|
+
{
|
|
51
|
+
const proxy_url = 'http://127.0.0.1:8080'
|
|
52
|
+
const video_url = 'https://example.com/video/master.m3u8'
|
|
53
|
+
const referer_url = 'https://example.com/videos.html'
|
|
54
|
+
const file_extension = '.m3u8'
|
|
55
|
+
|
|
56
|
+
const hls_proxy_url = `${proxy_url}/${ btoa(`${video_url}|${referer_url}`) }${file_extension}`
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
* [example Bash]: construction of URL to _HLS Proxy_ for video stream
|
|
60
|
+
```bash
|
|
61
|
+
proxy_url='http://127.0.0.1:8080'
|
|
62
|
+
video_url='https://example.com/video/master.m3u8'
|
|
63
|
+
file_extension='.m3u8'
|
|
64
|
+
|
|
65
|
+
hls_proxy_url="${proxy_url}/"$(echo -n "$video_url" | base64 --wrap=0)"$file_extension"
|
|
66
|
+
```
|
|
67
|
+
* [example Bash]: construction of URL to _HLS Proxy_ for video stream w/ "Referer" request header
|
|
68
|
+
```bash
|
|
69
|
+
proxy_url='http://127.0.0.1:8080'
|
|
70
|
+
video_url='https://example.com/video/master.m3u8'
|
|
71
|
+
referer_url='https://example.com/videos.html'
|
|
72
|
+
file_extension='.m3u8'
|
|
73
|
+
|
|
74
|
+
hls_proxy_url="${proxy_url}/"$(echo -n "${video_url}|${referer_url}" | base64 --wrap=0)"$file_extension"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
##### notes:
|
|
78
|
+
|
|
79
|
+
* adding a file extension to the base64 encoded video URL is optional
|
|
80
|
+
- doing so allows video clients to recognize that the URL being requested from _HLS Proxy_ is an HLS video stream
|
|
81
|
+
|
|
82
|
+
##### high-level tools that automate this task:
|
|
83
|
+
|
|
84
|
+
* refer to the section: [Other Projects](#other-projects)
|
|
85
|
+
|
|
86
|
+
- - - -
|
|
87
|
+
|
|
36
88
|
### Installation and Usage: Globally
|
|
37
89
|
|
|
38
90
|
#### How to: Install:
|
|
@@ -71,11 +123,20 @@ options:
|
|
|
71
123
|
--cache-key <number>
|
|
72
124
|
-v <number>
|
|
73
125
|
--acl-whitelist <ip_address_list>
|
|
126
|
+
--tls-cert <filepath>
|
|
127
|
+
--tls-key <filepath>
|
|
128
|
+
--tls-pass <filepath>
|
|
74
129
|
```
|
|
75
130
|
|
|
76
131
|
#### Options:
|
|
77
132
|
|
|
78
133
|
* _--tls_ is a flag to start HTTP**S** proxy, rather than HTTP
|
|
134
|
+
* used as shorthand to automatically configure the following options:
|
|
135
|
+
* _--tls-cert_
|
|
136
|
+
* _--tls-key_
|
|
137
|
+
* _--tls-pass_
|
|
138
|
+
* the values assigned to these options enable the use of a self-signed security certificate that is included in both the git repo and npm package, within the directory:
|
|
139
|
+
* [`./hls-proxy/servers/cert`](https://github.com/warren-bank/HLS-Proxy/tree/master/hls-proxy/servers/cert)
|
|
79
140
|
* _--host_ must be an IP address of the server on the LAN (so Chromecast can proxy requests through it)
|
|
80
141
|
* ex: `192.168.0.100`
|
|
81
142
|
* used to modify URLs in .m3u8 files
|
|
@@ -223,6 +284,10 @@ options:
|
|
|
223
284
|
* show an enhanced technical trace (useful while debugging unexpected behavior)
|
|
224
285
|
* _--acl-whitelist_ restricts proxy server access to clients at IP addresses in whitelist
|
|
225
286
|
* ex: `"192.168.1.100,192.168.1.101,192.168.1.102"`
|
|
287
|
+
* _--tls-cert_ is the filepath to a security certificate to use for HTTPS
|
|
288
|
+
* _--tls-key_ is the filepath to the private key for the _--tls-cert_ security certificate
|
|
289
|
+
* _--tls-pass_ is the filepath to a text file containing the security passphrase for the _--tls-key_ private key
|
|
290
|
+
* optional, not required when the _--tls-key_ private key was created without a security passphrase
|
|
226
291
|
|
|
227
292
|
#### Examples:
|
|
228
293
|
|
|
@@ -253,6 +318,9 @@ options:
|
|
|
253
318
|
9. start HTTPS proxy at default host:port and enable prefetch of 10 video segments<br>
|
|
254
319
|
`hlsd --tls --prefetch --max-segments 10`
|
|
255
320
|
|
|
321
|
+
10. start HTTPS proxy using a non-generic security certificate<br>
|
|
322
|
+
`hlsd --tls-cert "/path/to/cert.pem" --tls-key "/path/to/key.pem" --tls-pass "/path/to/pass.phrase"`
|
|
323
|
+
|
|
256
324
|
- - - -
|
|
257
325
|
|
|
258
326
|
### Installation and Usage: Working with a Local `git` Repo
|
|
@@ -304,29 +372,44 @@ npm run sudo [-- <options>]
|
|
|
304
372
|
5. start HTTPS proxy at default host:port with escalated privilege<br>
|
|
305
373
|
`npm run sudo -- --port "443" --tls`
|
|
306
374
|
|
|
307
|
-
6. start HTTP proxy at specific port and send custom request
|
|
375
|
+
6. start HTTP proxy at specific port and send custom "Referer" request header for specific video stream<br>
|
|
376
|
+
```bash
|
|
377
|
+
npm start -- --port "8080"
|
|
378
|
+
|
|
379
|
+
h_referer='http://XXX:80/page.html'
|
|
380
|
+
|
|
381
|
+
URL='https://httpbin.org/headers'
|
|
382
|
+
URL="${URL}|${h_referer}"
|
|
383
|
+
URL=$(echo -n "$URL" | base64 --wrap=0)
|
|
384
|
+
URL="http://127.0.0.1:8080/${URL}.json"
|
|
385
|
+
# URL='http://127.0.0.1:8080/aHR0cHM6Ly9odHRwYmluLm9yZy9oZWFkZXJzfGh0dHA6Ly9YWFg6ODAvcGFnZS5odG1s.json'
|
|
386
|
+
curl --silent "$URL"
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
7. start HTTP proxy at specific port and send custom request headers<br>
|
|
308
390
|
```bash
|
|
309
391
|
headers_file="${TMPDIR}/headers.json"
|
|
310
392
|
echo '{"Origin" : "http://XXX:80", "Referer": "http://XXX:80/page.html"}' > "$headers_file"
|
|
311
393
|
npm start -- --port "8080" --req-headers "$headers_file"
|
|
312
394
|
|
|
313
395
|
URL='https://httpbin.org/headers'
|
|
314
|
-
URL=$(echo "$URL" | base64)
|
|
396
|
+
URL=$(echo -n "$URL" | base64 --wrap=0)
|
|
315
397
|
URL="http://127.0.0.1:8080/${URL}.json"
|
|
398
|
+
# URL='http://127.0.0.1:8080/aHR0cHM6Ly9odHRwYmluLm9yZy9oZWFkZXJz.json'
|
|
316
399
|
curl --silent "$URL"
|
|
317
400
|
```
|
|
318
401
|
|
|
319
|
-
|
|
402
|
+
8. start HTTPS proxy at specific port and send custom request headers<br>
|
|
320
403
|
```bash
|
|
321
404
|
headers_file="${TMPDIR}/headers.json"
|
|
322
405
|
echo '{"Origin" : "http://XXX:80", "Referer": "http://XXX:80/page.html"}' > "$headers_file"
|
|
323
406
|
npm start -- --port "8081" --req-headers "$headers_file" --tls -v 1
|
|
324
407
|
|
|
325
|
-
URL='https://127.0.0.1:8081/
|
|
408
|
+
URL='https://127.0.0.1:8081/aHR0cHM6Ly9odHRwYmluLm9yZy9oZWFkZXJz.json'
|
|
326
409
|
curl --silent --insecure "$URL"
|
|
327
410
|
```
|
|
328
411
|
|
|
329
|
-
|
|
412
|
+
9. start HTTPS proxy at specific port and send custom request headers<br>
|
|
330
413
|
```bash
|
|
331
414
|
h_origin='http://XXX:80'
|
|
332
415
|
h_referer='http://XXX:80/page.html'
|
|
@@ -335,7 +418,7 @@ h_custom_1='X-Foo: 123'
|
|
|
335
418
|
h_custom_2='X-Bar: baz'
|
|
336
419
|
npm start -- --port "8081" --origin "$h_origin" --referer "$h_referer" --useragent "$h_useragent" --header "$h_custom_1" --header "$h_custom_2" --tls -v 1
|
|
337
420
|
|
|
338
|
-
URL='https://127.0.0.1:8081/
|
|
421
|
+
URL='https://127.0.0.1:8081/aHR0cHM6Ly9odHRwYmluLm9yZy9oZWFkZXJz.json'
|
|
339
422
|
curl --silent --insecure "$URL"
|
|
340
423
|
```
|
|
341
424
|
|
|
@@ -399,7 +482,7 @@ curl --silent --insecure "$URL"
|
|
|
399
482
|
* [there](https://warren-bank.github.io/crx-webcast-reloaded/external_website/index.html) is a selection of several HTML5 videos players
|
|
400
483
|
* each is better at some things and worse at others
|
|
401
484
|
* each integrates with a different Chromecast receiver app
|
|
402
|
-
* [there](https://warren-bank.github.io/crx-webcast-reloaded/external_website/proxy.html) is a page to help redirect the intercepted video URL through a local instance of
|
|
485
|
+
* [there](https://warren-bank.github.io/crx-webcast-reloaded/external_website/proxy.html) is a page to help redirect the intercepted video URL through a local instance of _HLS Proxy_
|
|
403
486
|
|
|
404
487
|
- - - -
|
|
405
488
|
|
package/hls-proxy/bin/hlsd.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
const {argv_vals, bootstrap_server} = require('./lib/process_argv')
|
|
4
4
|
|
|
5
|
-
const start_server = (argv_vals["--tls"]
|
|
5
|
+
const start_server = ((argv_vals["--tls-cert"] && argv_vals["--tls-key"]) || argv_vals["--tls"])
|
|
6
|
+
? require('../servers/start_https')
|
|
7
|
+
: require('../servers/start_http')
|
|
6
8
|
|
|
7
9
|
bootstrap_server(start_server)
|
|
@@ -1,31 +1,34 @@
|
|
|
1
|
-
const help = `
|
|
2
|
-
hlsd <options>
|
|
3
|
-
|
|
4
|
-
options:
|
|
5
|
-
========
|
|
6
|
-
--help
|
|
7
|
-
--version
|
|
8
|
-
--tls
|
|
9
|
-
--host <ip_address>
|
|
10
|
-
--port <number>
|
|
11
|
-
--req-headers <filepath>
|
|
12
|
-
--origin <header>
|
|
13
|
-
--referer <header>
|
|
14
|
-
--useragent <header>
|
|
15
|
-
--header <name=value>
|
|
16
|
-
--req-options <filepath>
|
|
17
|
-
--req-insecure
|
|
18
|
-
--req-secure-honor-server-cipher-order
|
|
19
|
-
--req-secure-ciphers <string>
|
|
20
|
-
--req-secure-protocol <string>
|
|
21
|
-
--req-secure-curve <string>
|
|
22
|
-
--hooks <filepath>
|
|
23
|
-
--prefetch
|
|
24
|
-
--max-segments <number>
|
|
25
|
-
--cache-timeout <number>
|
|
26
|
-
--cache-key <number>
|
|
27
|
-
-v <number>
|
|
28
|
-
--acl-whitelist <ip_address_list>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
const help = `
|
|
2
|
+
hlsd <options>
|
|
3
|
+
|
|
4
|
+
options:
|
|
5
|
+
========
|
|
6
|
+
--help
|
|
7
|
+
--version
|
|
8
|
+
--tls
|
|
9
|
+
--host <ip_address>
|
|
10
|
+
--port <number>
|
|
11
|
+
--req-headers <filepath>
|
|
12
|
+
--origin <header>
|
|
13
|
+
--referer <header>
|
|
14
|
+
--useragent <header>
|
|
15
|
+
--header <name=value>
|
|
16
|
+
--req-options <filepath>
|
|
17
|
+
--req-insecure
|
|
18
|
+
--req-secure-honor-server-cipher-order
|
|
19
|
+
--req-secure-ciphers <string>
|
|
20
|
+
--req-secure-protocol <string>
|
|
21
|
+
--req-secure-curve <string>
|
|
22
|
+
--hooks <filepath>
|
|
23
|
+
--prefetch
|
|
24
|
+
--max-segments <number>
|
|
25
|
+
--cache-timeout <number>
|
|
26
|
+
--cache-key <number>
|
|
27
|
+
-v <number>
|
|
28
|
+
--acl-whitelist <ip_address_list>
|
|
29
|
+
--tls-cert <filepath>
|
|
30
|
+
--tls-key <filepath>
|
|
31
|
+
--tls-pass <filepath>
|
|
32
|
+
`
|
|
33
|
+
|
|
34
|
+
module.exports = help
|
|
@@ -1,42 +1,53 @@
|
|
|
1
|
-
const
|
|
1
|
+
const process_argv = require('@warren-bank/node-process-argv')
|
|
2
|
+
|
|
3
|
+
const argv_flags = {
|
|
4
|
+
"--help": {bool: true},
|
|
5
|
+
"--version": {bool: true},
|
|
6
|
+
|
|
7
|
+
"--tls": {bool: true},
|
|
8
|
+
"--host": {},
|
|
9
|
+
"--port": {num: "int"},
|
|
10
|
+
|
|
11
|
+
"--req-headers": {file: "json"},
|
|
12
|
+
"--origin": {},
|
|
13
|
+
"--referer": {},
|
|
14
|
+
"--useragent": {},
|
|
15
|
+
"--header": {many: true},
|
|
16
|
+
|
|
17
|
+
"--req-options": {file: "json"},
|
|
18
|
+
"--req-insecure": {bool: true},
|
|
19
|
+
"--req-secure-honor-server-cipher-order": {bool: true},
|
|
20
|
+
"--req-secure-ciphers": {},
|
|
21
|
+
"--req-secure-protocol": {},
|
|
22
|
+
"--req-secure-curve": {},
|
|
23
|
+
|
|
24
|
+
"--hooks": {file: "module"},
|
|
25
|
+
|
|
26
|
+
"--prefetch": {bool: true},
|
|
27
|
+
"--max-segments": {num: "int"},
|
|
28
|
+
"--cache-timeout": {num: "int"},
|
|
29
|
+
"--cache-key": {num: "int"},
|
|
30
|
+
|
|
31
|
+
"-v": {num: "int"},
|
|
32
|
+
"--acl-whitelist": {},
|
|
33
|
+
|
|
34
|
+
"--tls-cert": {file: "path-exists"},
|
|
35
|
+
"--tls-key": {file: "path-exists"},
|
|
36
|
+
"--tls-pass": {file: "path-exists"}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const argv_flag_aliases = {
|
|
40
|
+
"--help": ["-h"]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let argv_vals = {}
|
|
2
44
|
|
|
3
|
-
let argv_vals
|
|
4
45
|
try {
|
|
5
|
-
argv_vals =
|
|
6
|
-
"--help": {bool: true},
|
|
7
|
-
"--version": {bool: true},
|
|
8
|
-
|
|
9
|
-
"--tls": {bool: true},
|
|
10
|
-
"--host": {},
|
|
11
|
-
"--port": {num: true},
|
|
12
|
-
|
|
13
|
-
"--req-headers": {file: "json"},
|
|
14
|
-
"--origin": {},
|
|
15
|
-
"--referer": {},
|
|
16
|
-
"--useragent": {},
|
|
17
|
-
"--header": {many: true},
|
|
18
|
-
|
|
19
|
-
"--req-options": {file: "json"},
|
|
20
|
-
"--req-insecure": {bool: true},
|
|
21
|
-
"--req-secure-honor-server-cipher-order": {bool: true},
|
|
22
|
-
"--req-secure-ciphers": {},
|
|
23
|
-
"--req-secure-protocol": {},
|
|
24
|
-
"--req-secure-curve": {},
|
|
25
|
-
|
|
26
|
-
"--hooks": {file: "module"},
|
|
27
|
-
|
|
28
|
-
"--prefetch": {bool: true},
|
|
29
|
-
"--max-segments": {num: true},
|
|
30
|
-
"--cache-timeout": {num: true},
|
|
31
|
-
"--cache-key": {num: true},
|
|
32
|
-
|
|
33
|
-
"-v": {num: true},
|
|
34
|
-
"--acl-whitelist": {}
|
|
35
|
-
}, true)
|
|
46
|
+
argv_vals = process_argv(argv_flags, argv_flag_aliases)
|
|
36
47
|
}
|
|
37
48
|
catch(e) {
|
|
38
49
|
console.log('ERROR: ' + e.message)
|
|
39
|
-
process.exit(
|
|
50
|
+
process.exit(1)
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
if (argv_vals["--help"]) {
|
|
@@ -161,7 +172,10 @@ const bootstrap_server = function(start_server) {
|
|
|
161
172
|
cache_timeout: argv_vals["--cache-timeout"],
|
|
162
173
|
cache_key: argv_vals["--cache-key"],
|
|
163
174
|
verbosity: argv_vals["-v"],
|
|
164
|
-
acl_whitelist: argv_vals["--acl-whitelist"]
|
|
175
|
+
acl_whitelist: argv_vals["--acl-whitelist"],
|
|
176
|
+
tls_cert: argv_vals["--tls-cert"],
|
|
177
|
+
tls_key: argv_vals["--tls-key"],
|
|
178
|
+
tls_pass: argv_vals["--tls-pass"]
|
|
165
179
|
})
|
|
166
180
|
}
|
|
167
181
|
|
package/hls-proxy/proxy.js
CHANGED
|
@@ -11,7 +11,7 @@ const base64_decode = function(str) {
|
|
|
11
11
|
return Buffer.from(str, 'base64').toString('binary')
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const proxy = function({server, host,
|
|
14
|
+
const proxy = function({server, host, is_secure, req_headers, req_options, hooks, cache_segments, max_segments, cache_timeout, cache_key, debug_level, acl_whitelist}) {
|
|
15
15
|
|
|
16
16
|
const debug = function() {
|
|
17
17
|
let args = [...arguments]
|
|
@@ -277,7 +277,7 @@ const proxy = function({server, host, port, is_secure, req_headers, req_options,
|
|
|
277
277
|
matching_url += `|${referer_url}`
|
|
278
278
|
|
|
279
279
|
let ts_file_ext = get_ts_file_ext(file_name, file_ext)
|
|
280
|
-
let redirected_url = `${ is_secure ? 'https' : 'http' }://${host}
|
|
280
|
+
let redirected_url = `${ is_secure ? 'https' : 'http' }://${host}/${ base64_encode(matching_url) }${ts_file_ext || file_ext || ''}`
|
|
281
281
|
debug(3, 'redirecting (proxied):', redirected_url)
|
|
282
282
|
|
|
283
283
|
return `${head}${redirected_url}${tail}`
|
|
@@ -390,10 +390,21 @@ const proxy = function({server, host, port, is_secure, req_headers, req_options,
|
|
|
390
390
|
add_CORS_headers(res)
|
|
391
391
|
|
|
392
392
|
const [url, referer_url] = (() => {
|
|
393
|
-
|
|
394
|
-
|
|
393
|
+
if (!regexs.wrap.test(req.url))
|
|
394
|
+
return ['', '']
|
|
395
|
+
|
|
396
|
+
let url, url_lc, index
|
|
397
|
+
|
|
398
|
+
url = base64_decode( req.url.replace(regexs.wrap, '$1') ).trim()
|
|
399
|
+
url_lc = url.toLowerCase()
|
|
400
|
+
|
|
401
|
+
index = url_lc.indexOf('http')
|
|
402
|
+
if (index !== 0)
|
|
403
|
+
return ['', '']
|
|
404
|
+
|
|
405
|
+
index = url_lc.indexOf('|http')
|
|
395
406
|
if (index >=0) {
|
|
396
|
-
|
|
407
|
+
const referer_url = url.substring(index + 1, url.length)
|
|
397
408
|
url = url.substring(0, index).trim()
|
|
398
409
|
return [url, referer_url]
|
|
399
410
|
}
|
|
@@ -402,6 +413,12 @@ const proxy = function({server, host, port, is_secure, req_headers, req_options,
|
|
|
402
413
|
}
|
|
403
414
|
})()
|
|
404
415
|
|
|
416
|
+
if (!url) {
|
|
417
|
+
res.writeHead(400)
|
|
418
|
+
res.end()
|
|
419
|
+
return
|
|
420
|
+
}
|
|
421
|
+
|
|
405
422
|
const is_m3u8 = regexs.m3u8.test(url)
|
|
406
423
|
|
|
407
424
|
const send_ts = function(segment) {
|
|
@@ -55,4 +55,52 @@ const prompt_user_to_choose_one_IP = function(cb) {
|
|
|
55
55
|
})
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
// -----------------------------------------------------------------------------
|
|
59
|
+
// input:
|
|
60
|
+
// * host (if provided by cli option)
|
|
61
|
+
// * port (if provided by cli option, otherwise default value for type of server)
|
|
62
|
+
// output:
|
|
63
|
+
// * Promise
|
|
64
|
+
// resolved value:
|
|
65
|
+
// * host
|
|
66
|
+
// - type: String
|
|
67
|
+
// - format: "${IP}:${port}"
|
|
68
|
+
// -----------------------------------------------------------------------------
|
|
69
|
+
// notes:
|
|
70
|
+
// * "--host" cli option can include an embedded port number
|
|
71
|
+
// - the embedded port number can be different from the value of "--port" (or default)
|
|
72
|
+
// * the value of "--port" (or default) is used to run the server and can be accessed on the local/private network (LAN)
|
|
73
|
+
// * the embedded port number can be used to access the server from a public network when port mapping is necessary
|
|
74
|
+
// * if "--host" is defined, but does not include an embedded port number
|
|
75
|
+
// - the value of "--port" (or default) is added to "--host"
|
|
76
|
+
// * if "--host" is undefined
|
|
77
|
+
// - a hostname is resolved
|
|
78
|
+
// - the value of "--port" (or default) is added to the resolved hostname
|
|
79
|
+
// -----------------------------------------------------------------------------
|
|
80
|
+
const prompt_and_normalize_IP = function(host, port) {
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
if (host) {
|
|
83
|
+
const parts = host.split(':')
|
|
84
|
+
|
|
85
|
+
if (parts.length > 1) {
|
|
86
|
+
host = parts[0]
|
|
87
|
+
|
|
88
|
+
const public_port = parseInt( parts[1], 10 )
|
|
89
|
+
if (! isNaN(public_port))
|
|
90
|
+
port = public_port
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (host) return resolve(host)
|
|
95
|
+
|
|
96
|
+
prompt_user_to_choose_one_IP((host) => resolve(host))
|
|
97
|
+
})
|
|
98
|
+
.then((host) => {
|
|
99
|
+
if (host === false)
|
|
100
|
+
host = 'localhost'
|
|
101
|
+
|
|
102
|
+
return `${host}:${port}`
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
module.exports = {IP, prompt: prompt_user_to_choose_one_IP, resolve: prompt_and_normalize_IP}
|
|
@@ -1,24 +1,16 @@
|
|
|
1
|
-
const
|
|
2
|
-
const proxy
|
|
3
|
-
const http
|
|
1
|
+
const resolve = require('./lib/LAN_IPs').resolve
|
|
2
|
+
const proxy = require('../proxy')
|
|
3
|
+
const http = require('http')
|
|
4
4
|
|
|
5
5
|
const start_server = function({host, port, req_headers, req_options, hooks, cache_segments, max_segments, cache_timeout, cache_key, verbosity, acl_whitelist}) {
|
|
6
6
|
if (!port || isNaN(port)) port = 80
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
if (host) return resolve(host)
|
|
10
|
-
|
|
11
|
-
prompt((host) => resolve(host))
|
|
12
|
-
})
|
|
8
|
+
resolve(host, port)
|
|
13
9
|
.then((host) => {
|
|
14
|
-
if (host === false) {
|
|
15
|
-
host = 'localhost'
|
|
16
|
-
}
|
|
17
|
-
|
|
18
10
|
const server = http.createServer()
|
|
19
|
-
proxy({server, host,
|
|
11
|
+
proxy({server, host, is_secure: false, req_headers, req_options, hooks, cache_segments, max_segments, cache_timeout, cache_key, debug_level: verbosity, acl_whitelist})
|
|
20
12
|
server.listen(port, function () {
|
|
21
|
-
console.log(`HTTP server is listening at: ${host}
|
|
13
|
+
console.log(`HTTP server is listening at: ${host}`)
|
|
22
14
|
})
|
|
23
15
|
})
|
|
24
16
|
}
|
|
@@ -1,34 +1,32 @@
|
|
|
1
|
-
const
|
|
2
|
-
const proxy
|
|
3
|
-
const https
|
|
4
|
-
const fs
|
|
1
|
+
const resolve = require('./lib/LAN_IPs').resolve
|
|
2
|
+
const proxy = require('../proxy')
|
|
3
|
+
const https = require('https')
|
|
4
|
+
const fs = require('fs')
|
|
5
5
|
|
|
6
|
-
const start_server = function({host, port, req_headers, req_options, hooks, cache_segments, max_segments, cache_timeout, cache_key, verbosity, acl_whitelist}) {
|
|
6
|
+
const start_server = function({host, port, req_headers, req_options, hooks, cache_segments, max_segments, cache_timeout, cache_key, verbosity, acl_whitelist, tls_cert, tls_key, tls_pass}) {
|
|
7
7
|
if (!port || isNaN(port)) port = 443
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
if (host) return resolve(host)
|
|
11
|
-
|
|
12
|
-
prompt((host) => resolve(host))
|
|
13
|
-
})
|
|
9
|
+
resolve(host, port)
|
|
14
10
|
.then((host) => {
|
|
15
|
-
if (host === false) {
|
|
16
|
-
host = 'localhost'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
11
|
// reference:
|
|
20
12
|
// https://aghassi.github.io/ssl-using-express-4/
|
|
21
13
|
|
|
22
|
-
const ssl_options =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
14
|
+
const ssl_options = (tls_cert && tls_key)
|
|
15
|
+
? {
|
|
16
|
+
cert: fs.readFileSync(tls_cert),
|
|
17
|
+
key: fs.readFileSync(tls_key),
|
|
18
|
+
passphrase: tls_pass ? fs.readFileSync(tls_pass, 'utf8') : ''
|
|
19
|
+
}
|
|
20
|
+
: {
|
|
21
|
+
cert: fs.readFileSync(`${__dirname}/cert/cert.pem`),
|
|
22
|
+
key: fs.readFileSync(`${__dirname}/cert/key.pem`),
|
|
23
|
+
passphrase: 'HLS-proxy'
|
|
24
|
+
}
|
|
27
25
|
|
|
28
26
|
const server = https.createServer(ssl_options)
|
|
29
|
-
proxy({server, host,
|
|
27
|
+
proxy({server, host, is_secure: true, req_headers, req_options, hooks, cache_segments, max_segments, cache_timeout, cache_key, debug_level: verbosity, acl_whitelist})
|
|
30
28
|
server.listen(port, function () {
|
|
31
|
-
console.log(`HTTPS server is listening at: ${host}
|
|
29
|
+
console.log(`HTTPS server is listening at: ${host}`)
|
|
32
30
|
})
|
|
33
31
|
})
|
|
34
32
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warren-bank/hls-proxy",
|
|
3
3
|
"description": "Node.js server to proxy HLS video streams",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.19.0",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"start": "node hls-proxy/bin/hlsd.js",
|
|
7
7
|
"sudo": "sudo node hls-proxy/bin/hlsd.js"
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"hlsd": "hls-proxy/bin/hlsd.js"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@warren-bank/node-
|
|
13
|
+
"@warren-bank/node-process-argv": "^1.2.1",
|
|
14
|
+
"@warren-bank/node-request": "^2.0.10"
|
|
14
15
|
},
|
|
15
16
|
"license": "GPL-2.0",
|
|
16
17
|
"author": {
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
|
|
3
|
-
// assumes that all arguments are passed with the convention: -key value
|
|
4
|
-
// where "-key" is a flag
|
|
5
|
-
|
|
6
|
-
const retrieve_flag_value = function(flag_opts, args, index, throw_error_if_value_matches_any_flag_key, flag_keys) {
|
|
7
|
-
let val
|
|
8
|
-
|
|
9
|
-
if (index >= 0) {
|
|
10
|
-
if (flag_opts && flag_opts["bool"]) {
|
|
11
|
-
val = true
|
|
12
|
-
}
|
|
13
|
-
else if (index + 1 < args.length) {
|
|
14
|
-
val = args[index + 1]
|
|
15
|
-
|
|
16
|
-
if (throw_error_if_value_matches_any_flag_key && (flag_keys.indexOf(val) >= 0)) {
|
|
17
|
-
throw new Error('The command-line contains option ' + val + ' at a position where a value for the previous option ' + args[index] + ' is expected.')
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (flag_opts && flag_opts["num"]) {
|
|
21
|
-
val = Number(val)
|
|
22
|
-
|
|
23
|
-
if (isNaN(val)) val = ""
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (flag_opts && flag_opts["file"]) {
|
|
27
|
-
try {
|
|
28
|
-
val = fs.realpathSync(val, {encoding: 'utf8'})
|
|
29
|
-
|
|
30
|
-
if ( (typeof flag_opts["file"] === "string") && (flag_opts["file"].toLowerCase() === "module") ) {
|
|
31
|
-
val = require(val)
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
val = fs.readFileSync(val, {encoding: 'utf8'})
|
|
35
|
-
|
|
36
|
-
if ( (typeof flag_opts["file"] === "string") && (flag_opts["file"].toLowerCase() === "json") ) {
|
|
37
|
-
val = JSON.parse(val)
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
catch(e){
|
|
42
|
-
val = ""
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (val === "") val = undefined
|
|
49
|
-
|
|
50
|
-
return val
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const grep_argv = function(flags, throw_error_if_value_matches_any_flag_key) {
|
|
54
|
-
const args = process.argv.slice(2)
|
|
55
|
-
const flag_keys = Object.keys(flags)
|
|
56
|
-
const vals = {}
|
|
57
|
-
|
|
58
|
-
if (args.length > 0) {
|
|
59
|
-
flag_keys.forEach((flag) => {
|
|
60
|
-
let flag_opts = flags[flag]
|
|
61
|
-
let is_array = flag_opts && flag_opts["many"]
|
|
62
|
-
let index = args.indexOf(flag)
|
|
63
|
-
let val
|
|
64
|
-
|
|
65
|
-
if (!is_array) {
|
|
66
|
-
val = retrieve_flag_value(flag_opts, args, index, throw_error_if_value_matches_any_flag_key, flag_keys)
|
|
67
|
-
|
|
68
|
-
if (val !== undefined) {
|
|
69
|
-
vals[flag] = val
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
vals[flag] = []
|
|
74
|
-
|
|
75
|
-
while (index >=0) {
|
|
76
|
-
val = retrieve_flag_value(flag_opts, args, index, throw_error_if_value_matches_any_flag_key, flag_keys)
|
|
77
|
-
|
|
78
|
-
if (val !== undefined) {
|
|
79
|
-
vals[flag].push(val)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
index = args.indexOf(flag, (index + 1))
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return vals
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
module.exports = grep_argv
|