-
Notifications
You must be signed in to change notification settings - Fork 80
/
Copy pathREADME.md
655 lines (573 loc) · 31.8 KB
/
README.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
### [_HLS Proxy_](https://github.com/warren-bank/HLS-Proxy) : HTTP Live Streaming Proxy
#### Basic Functionality:
* proxy .m3u8 files, and the video segments (.ts files) they internally reference
* to all proxied files:
* add permissive CORS response headers
* to .m3u8:
* modify contents such that URLs in the playlist will also pass through the proxy
#### Advanced Features:
* inject custom HTTP headers in all outbound proxied requests
* prefetch video segments (.ts files)
* use a hook function to conditionally decide which video segments to prefetch
* use a hook function to conditionally redirect URLs in the playlist (_before_ and/or _after_ they're modified to pass through the proxy)
* use a hook function to conditionally rewrite URLs after they're received by the proxy
#### Benefits:
* any video player (on the LAN) can access the proxied video stream
* including Chromecast
* prefetch and caching of video segments ahead-of-time makes playback of the video stream very stable
* solves buffering problems
* the proxy can easily be configured to bypass many of the security measures used by video servers to restrict access:
* CORS response headers (to XHR requests)
* used by web browsers to enforce a security policy that limits which website(s) may access the content
* HTTP request headers
* `Origin` and `Referer` are often inspected by the server
* when these headers don't match the site hosting the content, a `403 Forbidden` response is returned (in lieu of the requested data)
* restricted access to encryption keys
* often times the encrypted video segments (.ts files) are readily available, but the encryption keys are well protected
* if the keys can be obtained from another source, then a hook function can be used to redirect only those URL requests
- - - -
#### URL Format:
* [example Javascript]: construction of URL to _HLS Proxy_ for video stream
```javascript
{
const proxy_url = 'http://127.0.0.1:8080'
const video_url = 'https://example.com/video/master.m3u8'
const file_extension = '.m3u8'
const hls_proxy_url = `${proxy_url}/${ btoa(video_url) }${file_extension}`
}
```
* [example Javascript]: construction of URL to _HLS Proxy_ for video stream w/ "Referer" request header
```javascript
{
const proxy_url = 'http://127.0.0.1:8080'
const video_url = 'https://example.com/video/master.m3u8'
const referer_url = 'https://example.com/videos.html'
const file_extension = '.m3u8'
const hls_proxy_url = `${proxy_url}/${ btoa(`${video_url}|${referer_url}`) }${file_extension}`
}
```
* [example Bash]: construction of URL to _HLS Proxy_ for video stream
```bash
proxy_url='http://127.0.0.1:8080'
video_url='https://example.com/video/master.m3u8'
file_extension='.m3u8'
hls_proxy_url="${proxy_url}/"$(echo -n "$video_url" | base64 --wrap=0)"$file_extension"
```
* [example Bash]: construction of URL to _HLS Proxy_ for video stream w/ "Referer" request header
```bash
proxy_url='http://127.0.0.1:8080'
video_url='https://example.com/video/master.m3u8'
referer_url='https://example.com/videos.html'
file_extension='.m3u8'
hls_proxy_url="${proxy_url}/"$(echo -n "${video_url}|${referer_url}" | base64 --wrap=0)"$file_extension"
```
##### notes:
* adding a file extension to the base64 encoded video URL is highly recommended
- the following file extension values have important significance to indicate the type of file being requested:
* `.m3u8`<br>HLS manifest
* `.ts`<br>media segment
* `.key`<br>encryption key
* `.json`<br>JSON data
- though currently,
* `.m3u8`<br>is the only file extension that receives special treatment
* all other file types (including those without any file extension) are piped directly to the HTTP response
##### high-level tools that automate this task:
* refer to the section: [Other Projects](#other-projects)
- - - -
### Installation and Usage: Globally
#### How to: Install:
```bash
npm install --global "@warren-bank/hls-proxy"
```
#### How to: Run the server(s):
```bash
hlsd <options>
options:
========
--help
--version
--tls
--host <host>
--port <number>
--copy-req-headers
--req-headers <filepath>
--origin <header>
--referer <header>
--useragent <header>
--header <name=value>
--req-options <filepath>
--req-insecure
--req-secure-honor-server-cipher-order
--req-secure-ciphers <string>
--req-secure-protocol <string>
--req-secure-curve <string>
--hooks <filepath>
--prefetch
--max-segments <number>
--cache-timeout <number>
--cache-key <number>
--cache-storage <adapter>
--cache-storage-fs-dirpath <dirpath>
-v <number>
--acl-ip <ip_address_list>
--acl-pass <password_list>
--http-proxy <http[s]://[user:pass@]hostname:port>
--tls-cert <filepath>
--tls-key <filepath>
--tls-pass <filepath>
--manifest-extension <ext>
--segment-extension <ext>
```
#### Options:
* _--tls_ is a flag to start HTTP**S** proxy, rather than HTTP
* used as shorthand to automatically configure the following options:
* _--tls-cert_
* _--tls-key_
* _--tls-pass_
* 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:
* [`./hls-proxy/servers/cert`](https://github.com/warren-bank/HLS-Proxy/tree/master/hls-proxy/servers/cert)
* when all of these option are properly specified:
* the `https:` protocol is used by all URLs in modified HLS manifests
* _--host_ is an IP or hostname with an optional port number that can be resolved and is reachable by clients
* ex: `192.168.0.100:8080`
* used to modify URLs in .m3u8 files
* when this option is specified without a port number:
* the value of the _--port_ option is appended
* when this option is specified and the port number is `443`:
* the `https:` protocol is used by all URLs in modified HLS manifests
* when this option is not specified:
* the value of the ["Host"](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host) HTTP request header is used
* _--port_ is the port number that the server listens on
* ex: `8080`
* when this option is not specified:
* HTTP proxy binds to: `80`
* HTTPS proxy binds to: `443`
* _--copy-req-headers_ is a flag to enable the duplication of all HTTP request headers sent to the proxy → to the request made by the proxy to the video server
* _--req-headers_ is the filepath to a JSON data _Object_ containing key:value pairs
* each _key_ is the name of an HTTP header to send in every outbound request
* _--origin_ is the value of the corresponding HTTP request header
* _--referer_ is the value of the corresponding HTTP request header
* _--useragent_ is the value of the corresponding HTTP request header
* _--header_ is a single name:value pair
* this option can be used multiple times to include several HTTP request headers
* the pair can be written:
* "name: value"
* "name=value"
* "name = value"
* _--req-options_ is the filepath to a JSON data _Object_
* exposes the options _Object_ passed to low-level network request APIs:
* [`http.request(options)`](https://nodejs.org/api/http.html#http_http_request_options_callback)
* [`https.request(options)`](https://nodejs.org/api/https.html#https_https_request_options_callback)
* advanced __https__ request options:
* context of the secure request is obtained by passing the request options _Object_ to: [`tls.createSecureContext(options)`](https://nodejs.org/api/tls.html#tls_tls_createsecurecontext_options)
* configuration for the context of the secure request can be merged with the request options _Object_
* configuration keys of particular interest:
* `honorCipherOrder`
* default value: `false`
* `ciphers`
* default value: [`"ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA384:DHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA256:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!SRP:!CAMELLIA"`](https://nodejs.org/api/tls.html#tls_modifying_the_default_tls_cipher_suite)
* `secureProtocol`
* default value: [`"TLS_method"`](https://www.openssl.org/docs/man1.1.0/ssl/ssl.html#Dealing-with-Protocol-Methods)
* `ecdhCurve`
* default value: [`tls.DEFAULT_ECDH_CURVE`](https://nodejs.org/api/tls.html#tls_tls_default_ecdh_curve)
* the exact value depends on the version of node
* most commonly:
* older versions of node: `"prime256v1"`
* newer versions of node: `"auto"`
* _--req-insecure_ is a flag to override the following environment variable to disable certificate validation for secure __https__ requests:
* [`NODE_TLS_REJECT_UNAUTHORIZED`](https://nodejs.org/api/cli.html#cli_node_tls_reject_unauthorized_value)`= 0`
* equivalent to:
* `curl --insecure`
* `wget --no-check-certificate`
* _--req-secure-honor-server-cipher-order_ is a flag to set the following key in the request options _Object_ to configure the context for secure __https__ requests:
* `{honorCipherOrder: true}`
* _--req-secure-ciphers_ is the value to assign to the following key in the request options _Object_ to configure the context for secure __https__ requests:
* `{ciphers: value}`
* _--req-secure-protocol_ is the value to assign to the following key in the request options _Object_ to configure the context for secure __https__ requests:
* `{secureProtocol: value}`
* _--req-secure-curve_ is the value to assign to the following key in the request options _Object_ to configure the context for secure __https__ requests:
* `{ecdhCurve: value}`
* _--hooks_ is the filepath to a CommonJS module that exports a single JSON _Object_
* each _key_ is the name of a hook function
* each _value_ is the implementation of the corresponding _Function_
* hook function signatures:
* `"add_request_options": (url, is_m3u8) => request_options`
* conditionally add HTTP request options
* inputs:
* `url`
* string URL
* `is_m3u8`
* boolean that indicates whether `url` will request an HLS manifest
* return value:
* _Object_ having attributes that are combined with _--req-options_ and used to send the outbound request to `url`
* `"add_request_headers": (url, is_m3u8) => request_headers`
* conditionally add HTTP request headers
* return value:
* _Object_ containing key:value pairs that are combined with _--req-headers_
* each _key_ is the name of an HTTP header to send in the outbound request to `url`
* `"modify_m3u8_content": (m3u8_content, m3u8_url) => new_m3u8_content`
* conditionally modify the content of .m3u8 files __before__ they are parsed to extract URLs
* `"redirect": (url) => new_url`
* conditionally redirect the URLs encountered in .m3u8 files __before__ they are modified to pass through the proxy
* `"redirect_final": (url) => new_url`
* conditionally redirect the URLs encountered in .m3u8 files __after__ they are modified to pass through the proxy
* `"rewrite": (url) => new_url`
* conditionally rewrite the URLs requested by clients __before__ they are proxied
* `"prefetch": (url) => boolean`
* conditionally decide whether to prefetch video segments on a per-URL basis
* return value must be a strict boolean type (ie: `true` or `false`)
* otherwise, the default behavior supersedes
- to only prefetch .ts files
* `"prefetch_segments": (prefetch_urls, max_segments, is_vod, seg_duration_ms, perform_prefetch) => new_prefetch_urls`
* conditionally filter the list of video segment URLs that are pending prefetch, when more than _--max-segments_ are contained in an HLS manifest
* inputs:
* `prefetch_urls`
* array of string video segment URLs
* `max_segments`
* integer that denotes the max length of the return value
* `is_vod`
* boolean that indicates whether the HLS manifest is for video-on-demand
* if true:
* the video is not a live stream
* the HLS manifest is complete and contains URLs for every video segment that would be needed to play the entire stream from start to finish
* `seg_duration_ms`
* integer that represents the duration (ms) of each video segment in the HLS manifest
* `perform_prefetch`
* function that accepts an array of string video segment URLs, and immediately begins to prefetch all corresponding segments
* return value:
* array of string video segment URLs that is a subset of `prefetch_urls`
* can be emtpy (ex: when using `perform_prefetch`)
* pre-conditions:
* the length of `prefetch_urls` is > `max_segments`
* post-conditions:
* the length of the return value array is <= `max_segments`
* `"request_intervals": (add_request_interval) => {}`
* enables the use of a cookie jar for all outbound HTTP requests
* adds any number of timers that each execute at individually specified intervals
* when each timer executes, it is passed an HTTP request client that is preconfigured to:
- include the request headers that are specified by other relevant options
- utilize the same cookie jar as all other outbound HTTP requests
* this allows the implementation of custom logic that may be required by one or more video hosts to periodically refresh or update session cookies
* an example would better illustrate usage:
```javascript
module.exports = {
request_intervals: (add_request_interval) => {
add_request_interval(
0, // run timer once at startup to initialize cookies
(request) => {
request('https://example.com/login', {username: 'me', password: '12345'})
}
)
add_request_interval(
(1000 * 60 * 5), // run timer at 5 minute interval to refresh cookies
(request) => {
request('https://example.com/heart-beat')
}
)
}
}
```
* more advanced configuration of the call to the HTTP request client is possible
- the 1st parameter is required, and must be a _URL_ string
- the 2nd parameter is optional, and can contain POST data
- the 3rd parameter is optional, and can be used for more advanced configuration options
* usage of this HTTP request client is documented [here](https://github.com/warren-bank/node-request#api)
- specifically, pay careful attention to the signatures for:
* the latter two input parameters
* the attributes of the Object that is resolved by the Promise in the return value (if the content of the response is needed)
* _--prefetch_ is a flag to enable the prefetch and caching of video segments
* when .m3u8 files are downloaded and modified inflight, all of the URLs in the playlist are known
* at this time, it is possible to prefetch the video segments (.ts files)
* when the video segments (.ts files) are requested at a later time, the data is already cached (in memory) and can be returned immediately
* _--max-segments_ is the maximum number of video segments (.ts files) to hold in each cache
* this option is only meaningful when _--prefetch_ is enabled
* a cache is created for each unique HLS manifest URL
- all of the video segments (.ts files) associated with each distinct video stream are stored in isolation
* when any cache grows larger than this size, the oldest data is removed to make room to store new data
* when this option is not specified:
* default value: `20`
* _--cache-timeout_ is the maximum number of seconds that any segment cache can remain unused before its contents are cleared (to reduce wasted space in memory)
* this option is only meaningful when _--prefetch_ is enabled
* when this option is not specified:
* default value: `60`
* _--cache-key_ sets the type of string used to represent keys in the cache hashtable when logged
* this option is only meaningful when _--prefetch_ is enabled
* scope:
- v0.16.0 and earlier
* keys in the cache hashtable used this string representation
- v0.16.1 and later
* keys in the cache hashtable are full URLs
- the data structure to cache video segments (.ts files) was updated
- each unique HLS manifest is associated with a distinct FIFO list that holds _--max-segments_
- when a video segment is requested
* the proxy needs to search every FIFO list for a match
* when keys in the cache hashtable lose fidelity, collisions can occur and the wrong video segment can be returned
* full URLs are unique and guarantee correct behavior
* `0` (default):
* sequence number of .ts file w/ .ts file extension (ex: "123.ts")
* pros:
* shortest type of string
* makes the log output easiest to read
* cons:
* in the wild, I've encountered video servers that assign each .ts file a unique filename that always terminate with the same static sequence number
* this is a strange edge case, but this option provides an easy workaround
* `1`:
* full filename of .ts file
* `2`:
* full URL of .ts file
* _--cache-storage_ selects a storage adapter that is used to hold the cache of prefetched video segments
* this option is only meaningful when _--prefetch_ is enabled
* `memory` (default):
* uses RAM
* `filesystem`:
* each video segment is written to a new file within a specified directory
* filenames are random and unique
* _--cache-storage-fs-dirpath_ specifies the directory in which to save video segments when using a filesystem-based cache storage adapter
* this option is only meaningful when _--prefetch_ is enabled and _--cache-storage_ is `filesystem`
* _-v_ sets logging verbosity level:
* `-1`:
* silent
* `0` (default):
* show errors only
* `1`:
* show an informative amount of information
* `2`:
* show technical details
* `3`:
* show an enhanced technical trace (useful while debugging unexpected behavior)
* `4`:
* show the content of .m3u8 files (both before and after URLs are modified)
* _--acl-ip_ restricts proxy server access to clients at IP addresses in whitelist
* ex: `"192.168.1.100,192.168.1.101,192.168.1.102"`
* _--acl-pass_ restricts proxy server access to requests that include a `password` querystring parameter having a value in whitelist
* ex: `"1111,2222,3333,4444,5555"`
* --http-proxy enables all outbound HTTP and HTTPS requests from HLS-Proxy to be tunnelled through an additional external web proxy server
* SOCKS proxies are not supported
* ex: `http://myusername:[email protected]:1234`
* _--tls-cert_ is the filepath to a security certificate to use for HTTPS
* _--tls-key_ is the filepath to the private key for the _--tls-cert_ security certificate
* _--tls-pass_ is the filepath to a text file containing the security passphrase for the _--tls-key_ private key
* optional, not required when the _--tls-key_ private key was created without a security passphrase
* _--manifest-extension_ is the file extension associated with HLS manifests
* default value: `m3u8`
* _--segment-extension_ is the file extension associated with media segments
* default value: `ts`
#### Examples:
1. print help<br>
`hlsd --help`
2. print version<br>
`hlsd --version`
3. start HTTP proxy at default host:port<br>
`hlsd`
4. start HTTP proxy at default host and specific port<br>
`hlsd --port "8080"`
5. start HTTP proxy at specific host:port<br>
`hlsd --host "192.168.0.100" --port "8080"`
6. start HTTPS proxy at default host:port<br>
`hlsd --tls`
7. start HTTPS proxy at specific host:port<br>
`hlsd --tls --host "192.168.0.100" --port "8081"`
8. start HTTPS proxy at default host:port and send specific HTTP headers<br>
`hlsd --tls --req-headers "/path/to/request/headers.json"`
9. start HTTPS proxy at default host:port and enable prefetch of 10 video segments<br>
`hlsd --tls --prefetch --max-segments 10`
10. start HTTPS proxy using a non-generic security certificate<br>
`hlsd --tls-cert "/path/to/cert.pem" --tls-key "/path/to/key.pem" --tls-pass "/path/to/pass.phrase"`
- - - -
### Installation and Usage: Working with a Local `git` Repo
#### How to: Install:
```bash
git clone "https://github.com/warren-bank/HLS-Proxy.git"
cd "HLS-Proxy"
npm install
```
#### How to: Run the server(s):
```bash
# ----------------------------------------------------------------------
# If using a port number >= 1024 on Linux, or
# If using Windows:
# ----------------------------------------------------------------------
npm start [-- <options>]
# ----------------------------------------------------------------------
# https://www.w3.org/Daemon/User/Installation/PrivilegedPorts.html
#
# Linux considers port numbers < 1024 to be privileged.
# Use "sudo":
# ----------------------------------------------------------------------
npm run sudo [-- <options>]
```
#### Options:
* identical to the [command-line binary](#installation-and-usage-globally)
#### Examples:
1. print help<br>
`npm start -- --help`
2. start HTTP proxy at specific host:port<br>
`npm start -- --host "192.168.0.100" --port "8080"`
3. start HTTPS proxy at specific host:port<br>
`npm start -- --host "192.168.0.100" --port "8081" --tls`
4. start HTTP proxy at default host:port with escalated privilege<br>
`npm run sudo -- --port "80"`
5. start HTTPS proxy at default host:port with escalated privilege<br>
`npm run sudo -- --port "443" --tls`
6. start HTTP proxy at specific port and send custom "Referer" request header for specific video stream<br>
```bash
npm start -- --port "8080"
h_referer='http://XXX:80/page.html'
URL='https://httpbin.org/headers'
URL="${URL}|${h_referer}"
URL=$(echo -n "$URL" | base64 --wrap=0)
URL="http://127.0.0.1:8080/${URL}.json"
# URL='http://127.0.0.1:8080/aHR0cHM6Ly9odHRwYmluLm9yZy9oZWFkZXJzfGh0dHA6Ly9YWFg6ODAvcGFnZS5odG1s.json'
curl --silent "$URL"
```
7. start HTTP proxy at specific port and send custom request headers<br>
```bash
headers_file="${TMPDIR}/headers.json"
echo '{"Origin" : "http://XXX:80", "Referer": "http://XXX:80/page.html"}' > "$headers_file"
npm start -- --port "8080" --req-headers "$headers_file"
URL='https://httpbin.org/headers'
URL=$(echo -n "$URL" | base64 --wrap=0)
URL="http://127.0.0.1:8080/${URL}.json"
# URL='http://127.0.0.1:8080/aHR0cHM6Ly9odHRwYmluLm9yZy9oZWFkZXJz.json'
curl --silent "$URL"
```
8. start HTTPS proxy at specific port and send custom request headers<br>
```bash
headers_file="${TMPDIR}/headers.json"
echo '{"Origin" : "http://XXX:80", "Referer": "http://XXX:80/page.html"}' > "$headers_file"
npm start -- --port "8081" --req-headers "$headers_file" --tls -v 1
URL='https://127.0.0.1:8081/aHR0cHM6Ly9odHRwYmluLm9yZy9oZWFkZXJz.json'
curl --silent --insecure "$URL"
```
9. start HTTPS proxy at specific port and send custom request headers<br>
```bash
h_origin='http://XXX:80'
h_referer='http://XXX:80/page.html'
h_useragent='Chromium'
h_custom_1='X-Foo: 123'
h_custom_2='X-Bar: baz'
npm start -- --port "8081" --origin "$h_origin" --referer "$h_referer" --useragent "$h_useragent" --header "$h_custom_1" --header "$h_custom_2" --tls -v 1
URL='https://127.0.0.1:8081/aHR0cHM6Ly9odHRwYmluLm9yZy9oZWFkZXJz.json'
curl --silent --insecure "$URL"
```
- - - -
#### Observations:
* when playing the proxied HLS video stream in an HTML5 player in a Chromium web browser (ex: THEOplayer)
* if the page hosting the HTML5 video player is served from HTTPS:
* when running only the HTTP proxy server:
* the XHR requests from the player to the HTTP proxy server raise a security warning (insecure content)
* the XHR requests get elevated to HTTPS, which are unanswered (since the HTTPS proxy server isn't running)
* when running only the HTTPS proxy server:
* the XHR requests from the player to the HTTPS proxy server will silently fail
* this is because the HTTPS proxy server is using a self-signed security certificate
* this certificate needs to be (temporarily) allowed
* once it is, the video stream works perfectly
* to allow the certificate:
* browse to a URL hosted by the proxy server ( [example](https://127.0.0.1:443/aHR0cHM6Ly9naXRodWIuY29tL3dhcnJlbi1iYW5rL0hMUy1wcm94eS9yYXcvbWFzdGVyL3BhY2thZ2UuanNvbg==.json) )
* you should see the warning: `NET::ERR_CERT_AUTHORITY_INVALID` Your connection is not private
* click: `Advanced`
* click: `Proceed to 127.0.0.1 (unsafe)`
* done
* when playing the proxied HLS video stream on a Chromecast
* the HTTP proxy server works perfectly
* the HTTPS proxy server doesn't begin playback
* not sure why..
* probably has something to do with the Chromecast's browser security policies
* a more respectable security certificate (ie: more expensive) would probably fix it
#### Summary of (Rarely) Observed OpenSSL Connection Errors:
* error:<br>
`ssl3_check_cert_and_algorithm:dh key too small`
1. attempted fix:<br>
`--req-secure-ciphers "AES128-SHA"`
* error:<br>
`SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure`
1. attempted fix:<br>
`--req-secure-protocol "SSLv3_method"`
* result:<br>
`Error: SSLv3 methods disabled`
* issue:
* [node #3695](https://github.com/nodejs/node/issues/3695)
2. attempted fix:<br>
`--req-secure-curve "auto"`
- - - -
#### Other Projects:
##### (directly related, but very loosely coupled)
* [Webcast-Reloaded](https://github.com/warren-bank/crx-webcast-reloaded)
* consists of 2 parts:
1. a Chromium web browser extension (.crx)
* on each browser tab, it's silently watching the URL of all outbound requests
* every requested URL matching a regex pattern that identifies it to be a video file is displayed in the modal window that toggles open when the extension's icon is clicked
* links in this modal window open to URLs of component #2
2. a static website
* [there](https://warren-bank.github.io/crx-webcast-reloaded/external_website/index.html) is a selection of several HTML5 videos players
* each is better at some things and worse at others
* each integrates with a different Chromecast receiver app
* [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_
- - - -
#### Other Projects:
##### (unrelated, but somewhat similar in scope and purpose)
* [Streamlink](https://github.com/streamlink/streamlink)
* notes:
* this project has __way__ more features, and is __way__ more polished
* though its main purpose is to transcode online video with ffmpeg and pipe the output into another program, it can be configured to not load a video player and instead start a web server
* it can strongly support individual websites through single-purpose plugins
* it can also support streams via direct URLs
* using URLs from the wild will have mixed results, since cookies and headers and authentication aren't being managed by any plugin
* docs:
* [user guide](https://streamlink.github.io/#user-guide)
* [command-line usage](https://streamlink.github.io/cli.html#command-line-usage)
* [list of supported websites via plugins](https://streamlink.github.io/plugin_matrix.html)
* binaries:
* [Windows portable](https://github.com/streamlink/streamlink-portable/releases)
* minimum system requirements:
* Windows 7 SP1
* .NET Framework 4.5
* usage test:
* `streamlink --player-external-http --player-external-http-port 8080 --default-stream best --http-ignore-env --http-no-ssl-verify --url "https://XXX/video.m3u8"`
* usage test result:
* [doesn't appear to work with HTML5 video players or Chromecast](https://github.com/streamlink/streamlink/issues/1704#issuecomment-413661578)
* the server starts and works as it was intended, but something about the format of the data it "streams" is incompatible
* [VLC](https://portableapps.com/apps/music_video/vlc_portable) can play the video stream from the server, and be used to [render the video on Chromecast](https://github.com/warren-bank/HLS-Proxy/blob/master/.related/.recipes/01.%20Streamlink/notes.txt)
- - - -
#### Major Versions:
* `v1.x`
- commit history is in branch: [`v01`](https://github.com/warren-bank/HLS-Proxy/commits/v01)
- summary:
* m3u8 manifest parser uses regex patterns to identify all URL patterns without any special knowledge of the m3u8 manifest specification
* internal `proxy` module exports a function that accepts an instance of [`http.Server`](https://nodejs.org/api/http.html#class-httpserver) and adds event listeners to process requests
- system requirements:
* Node.js version: v8.6.0 (and higher)
- transitive [dependency](https://github.com/warren-bank/HLS-Proxy/blob/v1.0.1/package.json#L13-L14) requirements:
* v08.06.00+: [`@warren-bank/node-process-argv`](https://github.com/warren-bank/node-process-argv#requirements)
* v08.06.00+: [`@warren-bank/node-request`](https://github.com/warren-bank/node-request#requirements)
* `v2.x`
- commit history is in branch: [`v02`](https://github.com/warren-bank/HLS-Proxy/commits/v02)
- summary:
* m3u8 manifest parser uses regex patterns to identify all URL patterns without any special knowledge of the m3u8 manifest specification
* internal `proxy` module exports an Object containing event listeners to process requests that can be either:
- added to an instance of [`http.Server`](https://nodejs.org/api/http.html#class-httpserver)
- added to an [`Express.js`](https://github.com/expressjs/express) application as middleware to handle a custom route
* important limitation: since `/` is a valid character in a base64 encoded URL, the path for a custom route needs to end with a character that is not allowed in base64 encoding (ex: `'/proxy_/*'`)
- system requirements:
* Node.js version: v8.6.0 (and higher)
- transitive [dependency](https://github.com/warren-bank/HLS-Proxy/blob/v2.0.3/package.json#L13-L14) requirements:
* v08.06.00+: [`@warren-bank/node-process-argv`](https://github.com/warren-bank/node-process-argv#requirements)
* v08.06.00+: [`@warren-bank/node-request`](https://github.com/warren-bank/node-request#requirements)
* `v3.x`
- commit history is in branch: [`v03`](https://github.com/warren-bank/HLS-Proxy/commits/v03)
- summary:
* m3u8 manifest parser uses special knowledge of the m3u8 manifest specification to contextually identify URLs
* internal `proxy` module exports an Object containing event listeners to process requests that can be either:
- added to an instance of [`http.Server`](https://nodejs.org/api/http.html#class-httpserver)
- added to an [`Express.js`](https://github.com/expressjs/express) application as middleware to handle a custom route
* important requirement: the path for a custom route needs to include exactly one unnamed [parameter](https://expressjs.com/en/guide/routing.html#route-parameters) that matches the base64 encoded URL and (optionally) a file extension (ex: `'/proxy/*'`)
* the use of nested routers is supported
- system requirements:
* Node.js version: v8.6.0 (and higher)
- transitive [dependency](https://github.com/warren-bank/HLS-Proxy/blob/v3.5.1/package.json#L13-L14) requirements:
* v08.06.00+: [`@warren-bank/node-process-argv`](https://github.com/warren-bank/node-process-argv#requirements)
* v08.06.00+: [`@warren-bank/node-request`](https://github.com/warren-bank/node-request#requirements)
- - - -
#### Legal:
* copyright: [Warren Bank](https://github.com/warren-bank)
* license: [GPL-2.0](https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt)