@warren-bank/hls-proxy 3.1.2 → 3.2.1

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.
@@ -1,5 +1,7 @@
1
1
  const request = require('@warren-bank/node-request').request
2
+ const cookies = require('./cookies')
2
3
  const parser = require('./manifest_parser')
4
+ const timers = require('./timers')
3
5
  const utils = require('./utils')
4
6
 
5
7
  const get_middleware = function(params) {
@@ -70,7 +72,7 @@ const get_middleware = function(params) {
70
72
  debug(1, 'proxying:', url)
71
73
  debug(3, 'm3u8:', (is_m3u8 ? 'true' : 'false'))
72
74
 
73
- request(options, '', {binary: !is_m3u8, stream: !is_m3u8})
75
+ request(options, '', {binary: !is_m3u8, stream: !is_m3u8, cookieJar: cookies.getCookieJar()})
74
76
  .then(({redirects, response}) => {
75
77
  debug(2, 'proxied response:', {status_code: response.statusCode, headers: response.headers, redirects})
76
78
 
@@ -93,6 +95,8 @@ const get_middleware = function(params) {
93
95
  })
94
96
  }
95
97
 
98
+ timers.initialize_timers(params)
99
+
96
100
  return middleware
97
101
  }
98
102
 
@@ -1,4 +1,5 @@
1
1
  const request = require('@warren-bank/node-request').request
2
+ const cookies = require('./cookies')
2
3
  const utils = require('./utils')
3
4
 
4
5
  module.exports = function(params) {
@@ -175,7 +176,7 @@ module.exports = function(params) {
175
176
  ts[index] = {key: get_privatekey_from_url(url), databuffer: false}
176
177
 
177
178
  let options = get_request_options(url, /* is_m3u8= */ false, referer_url)
178
- promise = request(options, '', {binary: true, stream: false})
179
+ promise = request(options, '', {binary: true, stream: false, cookieJar: cookies.getCookieJar()})
179
180
  .then(({redirects, response}) => {
180
181
  debug(1, `prefetch (complete, ${response.length} bytes):`, debug_url)
181
182
  debug(2, 'prefetch response:', {status_code: response.statusCode, headers: response.headers, redirects})
@@ -0,0 +1,44 @@
1
+ const request = require('@warren-bank/node-request').request
2
+ const cookies = require('./cookies')
3
+ const utils = require('./utils')
4
+
5
+ const initialize_timers = function(params) {
6
+ const {hooks} = params
7
+
8
+ if (hooks && (hooks instanceof Object) && hooks.request_intervals && (typeof hooks.request_intervals === 'function')) {
9
+ cookies.useCookieJar()
10
+
11
+ const get_request_options = utils.get_request_options.bind(null, params)
12
+
13
+ const request_wrapper = function(url, POST_data, user_config) {
14
+ const options = get_request_options(url, /* is_m3u8= */ false, /* referer_url= */ null)
15
+ const config = Object.assign(
16
+ {},
17
+ (user_config || {}),
18
+ {
19
+ cookieJar: cookies.getCookieJar()
20
+ }
21
+ )
22
+
23
+ return request(options, POST_data, config)
24
+ }
25
+
26
+ const add_request_interval = function(delay_ms, callback) {
27
+ if (!delay_ms || (typeof delay_ms !== 'number') || isNaN(delay_ms) || (delay_ms < 0)) {
28
+ callback(request_wrapper)
29
+ }
30
+ else {
31
+ setInterval(
32
+ callback.bind(null, request_wrapper),
33
+ delay_ms
34
+ )
35
+ }
36
+ }
37
+
38
+ hooks.request_intervals(add_request_interval)
39
+ }
40
+ }
41
+
42
+ module.exports = {
43
+ initialize_timers
44
+ }
@@ -1,157 +1,157 @@
1
- const parse_url = require('@warren-bank/url').parse
2
-
3
- const regexs = {
4
- req_url: new RegExp('^(.*)/([^\\._/\\?#]+)(?:[\\._]([^/\\?#]*))?(?:[\\?#].*)?$', 'i'),
5
- origin: new RegExp('^(https?://[^/]+)(?:/.*)?$', 'i')
6
- }
7
-
8
- // btoa
9
- const base64_encode = function(str) {
10
- return Buffer.from(str, 'binary').toString('base64')
11
- }
12
-
13
- // atob
14
- const base64_decode = function(str) {
15
- return Buffer.from(str, 'base64').toString('binary')
16
- }
17
-
18
- const parse_req_url = function(params, req) {
19
- const {is_secure, host} = params
20
-
21
- const result = {redirected_base_url: '', url_type: '', url: '', referer_url: ''}
22
-
23
- const matches = regexs.req_url.exec(req.url)
24
-
25
- if (matches) {
26
- result.redirected_base_url = `${ is_secure ? 'https' : 'http' }://${host || req.headers.host}${matches[1] || ''}`
27
-
28
- if (matches[3])
29
- result.url_type = matches[3].toLowerCase().trim()
30
-
31
- let url, url_lc, index
32
-
33
- url = base64_decode( matches[2] ).trim()
34
- url_lc = url.toLowerCase()
35
- index = url_lc.indexOf('http')
36
-
37
- if (index === 0) {
38
- index = url_lc.indexOf('|http')
39
-
40
- if (index > 0) {
41
- result.referer_url = url.substring(index + 1, url.length)
42
-
43
- url = url.substring(0, index).trim()
44
- }
45
- result.url = url
46
- }
47
- }
48
-
49
- return result
50
- }
51
-
52
- const get_content_type = function(url_type) {
53
- let content_type
54
- switch(url_type) {
55
- case 'm3u8':
56
- content_type = 'application/x-mpegurl'
57
- break
58
- case 'ts':
59
- content_type = 'video/MP2T'
60
- break
61
- case 'json':
62
- content_type = 'application/json'
63
- break
64
- case 'key':
65
- case 'other':
66
- default:
67
- content_type = 'application/octet-stream'
68
- break
69
- }
70
- return content_type
71
- }
72
-
73
- const add_CORS_headers = function(res) {
74
- res.setHeader('Access-Control-Allow-Origin', '*')
75
- res.setHeader('Access-Control-Allow-Methods', '*')
76
- res.setHeader('Access-Control-Allow-Headers', '*')
77
- res.setHeader('Access-Control-Allow-Credentials', 'true')
78
- res.setHeader('Access-Control-Max-Age', '86400')
79
- }
80
-
81
- const debug = function() {
82
- const args = [...arguments]
83
- const params = args.shift()
84
- const verbosity = args.shift()
85
- const append_LF = true
86
-
87
- const {debug_level} = params
88
-
89
- if (append_LF) args.push("\n")
90
-
91
- if (debug_level >= verbosity) {
92
- console.log.apply(console.log, args)
93
- }
94
- }
95
-
96
- const get_request_options = function(params, url, is_m3u8, referer_url) {
97
- const {req_headers, req_options, hooks} = params
98
-
99
- const additional_req_options = (hooks && (hooks instanceof Object) && hooks.add_request_options && (typeof hooks.add_request_options === 'function'))
100
- ? hooks.add_request_options(url, is_m3u8)
101
- : null
102
-
103
- const additional_req_headers = (hooks && (hooks instanceof Object) && hooks.add_request_headers && (typeof hooks.add_request_headers === 'function'))
104
- ? hooks.add_request_headers(url, is_m3u8)
105
- : null
106
-
107
- if (!req_options && !additional_req_options && !req_headers && !additional_req_headers && !referer_url) return url
108
-
109
- const request_options = Object.assign(
110
- {},
111
- parse_url(url),
112
- (req_options || {}),
113
- (additional_req_options || {})
114
- )
115
-
116
- request_options.headers = Object.assign(
117
- {},
118
- (( req_options && req_options.headers) ? req_options.headers : {}),
119
- ((additional_req_options && additional_req_options.headers) ? additional_req_options.headers : {}),
120
- (req_headers || {}),
121
- (additional_req_headers || {}),
122
- (referer_url ? {"referer": referer_url, "origin": referer_url.replace(regexs.origin, '$1')} : {})
123
- )
124
-
125
- return request_options
126
- }
127
-
128
- const should_prefetch_url = function(params, url, url_type) {
129
- const {hooks, cache_segments} = params
130
-
131
- let do_prefetch = !!url && !!cache_segments
132
-
133
- if (do_prefetch) {
134
- do_prefetch = (url_type === 'ts') || (url_type === 'key')
135
-
136
- if (hooks && (hooks instanceof Object) && hooks.prefetch && (typeof hooks.prefetch === 'function')) {
137
- const override_prefetch = hooks.prefetch(url, url_type)
138
-
139
- if ((typeof override_prefetch === 'boolean') && (override_prefetch !== do_prefetch)) {
140
- debug(params, 3, 'prefetch override:', (override_prefetch ? 'allow' : 'deny'), url)
141
- do_prefetch = override_prefetch
142
- }
143
- }
144
- }
145
- return do_prefetch
146
- }
147
-
148
- module.exports = {
149
- base64_encode,
150
- base64_decode,
151
- parse_req_url,
152
- get_content_type,
153
- add_CORS_headers,
154
- debug,
155
- get_request_options,
156
- should_prefetch_url
157
- }
1
+ const parse_url = require('@warren-bank/url').parse
2
+
3
+ const regexs = {
4
+ req_url: new RegExp('^(.*?)/([a-zA-Z0-9\\+/=]+)(?:[\\._]([^/\\?#]*))?(?:[\\?#].*)?$'),
5
+ origin: new RegExp('^(https?://[^/]+)(?:/.*)?$', 'i')
6
+ }
7
+
8
+ // btoa
9
+ const base64_encode = function(str) {
10
+ return Buffer.from(str, 'binary').toString('base64')
11
+ }
12
+
13
+ // atob
14
+ const base64_decode = function(str) {
15
+ return Buffer.from(str, 'base64').toString('binary')
16
+ }
17
+
18
+ const parse_req_url = function(params, req) {
19
+ const {is_secure, host} = params
20
+
21
+ const result = {redirected_base_url: '', url_type: '', url: '', referer_url: ''}
22
+
23
+ const matches = regexs.req_url.exec(req.url)
24
+
25
+ if (matches) {
26
+ result.redirected_base_url = `${ is_secure ? 'https' : 'http' }://${host || req.headers.host}${matches[1] || ''}`
27
+
28
+ if (matches[3])
29
+ result.url_type = matches[3].toLowerCase().trim()
30
+
31
+ let url, url_lc, index
32
+
33
+ url = base64_decode( matches[2] ).trim()
34
+ url_lc = url.toLowerCase()
35
+ index = url_lc.indexOf('http')
36
+
37
+ if (index === 0) {
38
+ index = url_lc.indexOf('|http')
39
+
40
+ if (index > 0) {
41
+ result.referer_url = url.substring(index + 1, url.length)
42
+
43
+ url = url.substring(0, index).trim()
44
+ }
45
+ result.url = url
46
+ }
47
+ }
48
+
49
+ return result
50
+ }
51
+
52
+ const get_content_type = function(url_type) {
53
+ let content_type
54
+ switch(url_type) {
55
+ case 'm3u8':
56
+ content_type = 'application/x-mpegurl'
57
+ break
58
+ case 'ts':
59
+ content_type = 'video/MP2T'
60
+ break
61
+ case 'json':
62
+ content_type = 'application/json'
63
+ break
64
+ case 'key':
65
+ case 'other':
66
+ default:
67
+ content_type = 'application/octet-stream'
68
+ break
69
+ }
70
+ return content_type
71
+ }
72
+
73
+ const add_CORS_headers = function(res) {
74
+ res.setHeader('Access-Control-Allow-Origin', '*')
75
+ res.setHeader('Access-Control-Allow-Methods', '*')
76
+ res.setHeader('Access-Control-Allow-Headers', '*')
77
+ res.setHeader('Access-Control-Allow-Credentials', 'true')
78
+ res.setHeader('Access-Control-Max-Age', '86400')
79
+ }
80
+
81
+ const debug = function() {
82
+ const args = [...arguments]
83
+ const params = args.shift()
84
+ const verbosity = args.shift()
85
+ const append_LF = true
86
+
87
+ const {debug_level} = params
88
+
89
+ if (append_LF) args.push("\n")
90
+
91
+ if (debug_level >= verbosity) {
92
+ console.log.apply(console.log, args)
93
+ }
94
+ }
95
+
96
+ const get_request_options = function(params, url, is_m3u8, referer_url) {
97
+ const {req_headers, req_options, hooks} = params
98
+
99
+ const additional_req_options = (hooks && (hooks instanceof Object) && hooks.add_request_options && (typeof hooks.add_request_options === 'function'))
100
+ ? hooks.add_request_options(url, is_m3u8)
101
+ : null
102
+
103
+ const additional_req_headers = (hooks && (hooks instanceof Object) && hooks.add_request_headers && (typeof hooks.add_request_headers === 'function'))
104
+ ? hooks.add_request_headers(url, is_m3u8)
105
+ : null
106
+
107
+ if (!req_options && !additional_req_options && !req_headers && !additional_req_headers && !referer_url) return url
108
+
109
+ const request_options = Object.assign(
110
+ {},
111
+ parse_url(url),
112
+ (req_options || {}),
113
+ (additional_req_options || {})
114
+ )
115
+
116
+ request_options.headers = Object.assign(
117
+ {},
118
+ (( req_options && req_options.headers) ? req_options.headers : {}),
119
+ ((additional_req_options && additional_req_options.headers) ? additional_req_options.headers : {}),
120
+ (req_headers || {}),
121
+ (additional_req_headers || {}),
122
+ (referer_url ? {"referer": referer_url, "origin": referer_url.replace(regexs.origin, '$1')} : {})
123
+ )
124
+
125
+ return request_options
126
+ }
127
+
128
+ const should_prefetch_url = function(params, url, url_type) {
129
+ const {hooks, cache_segments} = params
130
+
131
+ let do_prefetch = !!url && !!cache_segments
132
+
133
+ if (do_prefetch) {
134
+ do_prefetch = (url_type === 'ts') || (url_type === 'key')
135
+
136
+ if (hooks && (hooks instanceof Object) && hooks.prefetch && (typeof hooks.prefetch === 'function')) {
137
+ const override_prefetch = hooks.prefetch(url, url_type)
138
+
139
+ if ((typeof override_prefetch === 'boolean') && (override_prefetch !== do_prefetch)) {
140
+ debug(params, 3, 'prefetch override:', (override_prefetch ? 'allow' : 'deny'), url)
141
+ do_prefetch = override_prefetch
142
+ }
143
+ }
144
+ }
145
+ return do_prefetch
146
+ }
147
+
148
+ module.exports = {
149
+ base64_encode,
150
+ base64_decode,
151
+ parse_req_url,
152
+ get_content_type,
153
+ add_CORS_headers,
154
+ debug,
155
+ get_request_options,
156
+ should_prefetch_url
157
+ }
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": "3.1.2",
4
+ "version": "3.2.1",
5
5
  "scripts": {
6
6
  "start": "node hls-proxy/bin/hlsd.js",
7
7
  "sudo": "sudo node hls-proxy/bin/hlsd.js"
@@ -12,7 +12,8 @@
12
12
  "dependencies": {
13
13
  "@warren-bank/node-process-argv": "^1.2.1",
14
14
  "@warren-bank/node-request": "^2.0.10",
15
- "@warren-bank/url": "^3.1.0"
15
+ "@warren-bank/url": "^3.1.0",
16
+ "tough-cookie": "^3.0.1"
16
17
  },
17
18
  "license": "GPL-2.0",
18
19
  "author": {