recycleactor commited on
Commit
4aa94d5
·
verified ·
1 Parent(s): 71dcd6c

Upload 3 files

Browse files
Files changed (3) hide show
  1. package-lock.json +4 -130
  2. package.json +1 -2
  3. server.js +95 -10
package-lock.json CHANGED
@@ -11,11 +11,10 @@
11
  "@babel/core": "^7.26.10",
12
  "@babel/preset-env": "^7.26.9",
13
  "express": "^4.19.2",
14
- "http-proxy-middleware": "^4.2.0",
15
  "regenerator-runtime": "^0.14.1"
16
  },
17
  "engines": {
18
- "node": ">=18"
19
  }
20
  },
21
  "node_modules/@babel/code-frame": {
@@ -1564,9 +1563,9 @@
1564
  }
1565
  },
1566
  "node_modules/baseline-browser-mapping": {
1567
- "version": "2.11.7",
1568
- "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.7.tgz",
1569
- "integrity": "sha512-APw5YuIQAg6L9w4sHDI6j26DGFJI6RpYOhnkMPdC9lWbkKvsyPHzDsve1yd73lk21yz7Y09Kci8B2Pp9FonzWA==",
1570
  "license": "Apache-2.0",
1571
  "bin": {
1572
  "baseline-browser-mapping": "dist/cli.cjs"
@@ -1614,18 +1613,6 @@
1614
  "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
1615
  "license": "MIT"
1616
  },
1617
- "node_modules/braces": {
1618
- "version": "3.0.3",
1619
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
1620
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
1621
- "license": "MIT",
1622
- "dependencies": {
1623
- "fill-range": "^7.1.1"
1624
- },
1625
- "engines": {
1626
- "node": ">=8"
1627
- }
1628
- },
1629
  "node_modules/browserslist": {
1630
  "version": "4.28.7",
1631
  "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz",
@@ -1967,18 +1954,6 @@
1967
  "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
1968
  "license": "MIT"
1969
  },
1970
- "node_modules/fill-range": {
1971
- "version": "7.1.1",
1972
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
1973
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
1974
- "license": "MIT",
1975
- "dependencies": {
1976
- "to-regex-range": "^5.0.1"
1977
- },
1978
- "engines": {
1979
- "node": ">=8"
1980
- }
1981
- },
1982
  "node_modules/finalhandler": {
1983
  "version": "1.3.2",
1984
  "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
@@ -2141,28 +2116,6 @@
2141
  "url": "https://opencollective.com/express"
2142
  }
2143
  },
2144
- "node_modules/http-proxy-middleware": {
2145
- "version": "4.2.0",
2146
- "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-4.2.0.tgz",
2147
- "integrity": "sha512-ZA+oNOoM+GLoFTIzhkJptVQov73Srep2LBqhF8hG8CIPKO3nam1jonXVQ/QUH8RbwsmaaVz2SOJdzBNBHNtKbw==",
2148
- "license": "MIT",
2149
- "dependencies": {
2150
- "debug": "^4.4.3",
2151
- "httpxy": "^0.5.4",
2152
- "is-glob": "^4.0.3",
2153
- "is-plain-obj": "^4.1.0",
2154
- "micromatch": "^4.0.8"
2155
- },
2156
- "engines": {
2157
- "node": "^22.15.0 || ^24.0.0 || >=26.0.0"
2158
- }
2159
- },
2160
- "node_modules/httpxy": {
2161
- "version": "0.5.5",
2162
- "resolved": "https://registry.npmjs.org/httpxy/-/httpxy-0.5.5.tgz",
2163
- "integrity": "sha512-uDjmnPyp1q4Sgzf3w+J/Fc6UqcCEj0x4Wjp7OqK5dGhNeDgpyrAmnS6ey8QWrX3SWDon2DMKf9sBa5X9+CVyMA==",
2164
- "license": "MIT"
2165
- },
2166
  "node_modules/iconv-lite": {
2167
  "version": "0.4.24",
2168
  "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -2205,48 +2158,6 @@
2205
  "url": "https://github.com/sponsors/ljharb"
2206
  }
2207
  },
2208
- "node_modules/is-extglob": {
2209
- "version": "2.1.1",
2210
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
2211
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
2212
- "license": "MIT",
2213
- "engines": {
2214
- "node": ">=0.10.0"
2215
- }
2216
- },
2217
- "node_modules/is-glob": {
2218
- "version": "4.0.3",
2219
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
2220
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
2221
- "license": "MIT",
2222
- "dependencies": {
2223
- "is-extglob": "^2.1.1"
2224
- },
2225
- "engines": {
2226
- "node": ">=0.10.0"
2227
- }
2228
- },
2229
- "node_modules/is-number": {
2230
- "version": "7.0.0",
2231
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
2232
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
2233
- "license": "MIT",
2234
- "engines": {
2235
- "node": ">=0.12.0"
2236
- }
2237
- },
2238
- "node_modules/is-plain-obj": {
2239
- "version": "4.1.0",
2240
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
2241
- "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
2242
- "license": "MIT",
2243
- "engines": {
2244
- "node": ">=12"
2245
- },
2246
- "funding": {
2247
- "url": "https://github.com/sponsors/sindresorhus"
2248
- }
2249
- },
2250
  "node_modules/js-tokens": {
2251
  "version": "4.0.0",
2252
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -2328,19 +2239,6 @@
2328
  "node": ">= 0.6"
2329
  }
2330
  },
2331
- "node_modules/micromatch": {
2332
- "version": "4.0.8",
2333
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
2334
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
2335
- "license": "MIT",
2336
- "dependencies": {
2337
- "braces": "^3.0.3",
2338
- "picomatch": "^2.3.1"
2339
- },
2340
- "engines": {
2341
- "node": ">=8.6"
2342
- }
2343
- },
2344
  "node_modules/mime": {
2345
  "version": "1.6.0",
2346
  "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
@@ -2449,18 +2347,6 @@
2449
  "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
2450
  "license": "ISC"
2451
  },
2452
- "node_modules/picomatch": {
2453
- "version": "2.3.2",
2454
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
2455
- "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
2456
- "license": "MIT",
2457
- "engines": {
2458
- "node": ">=8.6"
2459
- },
2460
- "funding": {
2461
- "url": "https://github.com/sponsors/jonschlinkert"
2462
- }
2463
- },
2464
  "node_modules/proxy-addr": {
2465
  "version": "2.0.7",
2466
  "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
@@ -2782,18 +2668,6 @@
2782
  "url": "https://github.com/sponsors/ljharb"
2783
  }
2784
  },
2785
- "node_modules/to-regex-range": {
2786
- "version": "5.0.1",
2787
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
2788
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
2789
- "license": "MIT",
2790
- "dependencies": {
2791
- "is-number": "^7.0.0"
2792
- },
2793
- "engines": {
2794
- "node": ">=8.0"
2795
- }
2796
- },
2797
  "node_modules/toidentifier": {
2798
  "version": "1.0.1",
2799
  "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
 
11
  "@babel/core": "^7.26.10",
12
  "@babel/preset-env": "^7.26.9",
13
  "express": "^4.19.2",
 
14
  "regenerator-runtime": "^0.14.1"
15
  },
16
  "engines": {
17
+ "node": ">=20"
18
  }
19
  },
20
  "node_modules/@babel/code-frame": {
 
1563
  }
1564
  },
1565
  "node_modules/baseline-browser-mapping": {
1566
+ "version": "2.11.8",
1567
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.8.tgz",
1568
+ "integrity": "sha512-zAgkquC2WYF0PIc6XbNYkA2uuxxFavzgmX61R+dHDUa558V8Ejf8ozTZFR6QzM24RWu4kBcRkhJ5kpz77j9fnQ==",
1569
  "license": "Apache-2.0",
1570
  "bin": {
1571
  "baseline-browser-mapping": "dist/cli.cjs"
 
1613
  "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
1614
  "license": "MIT"
1615
  },
 
 
 
 
 
 
 
 
 
 
 
 
1616
  "node_modules/browserslist": {
1617
  "version": "4.28.7",
1618
  "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz",
 
1954
  "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
1955
  "license": "MIT"
1956
  },
 
 
 
 
 
 
 
 
 
 
 
 
1957
  "node_modules/finalhandler": {
1958
  "version": "1.3.2",
1959
  "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
 
2116
  "url": "https://opencollective.com/express"
2117
  }
2118
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2119
  "node_modules/iconv-lite": {
2120
  "version": "0.4.24",
2121
  "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
 
2158
  "url": "https://github.com/sponsors/ljharb"
2159
  }
2160
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2161
  "node_modules/js-tokens": {
2162
  "version": "4.0.0",
2163
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
 
2239
  "node": ">= 0.6"
2240
  }
2241
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
2242
  "node_modules/mime": {
2243
  "version": "1.6.0",
2244
  "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
 
2347
  "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
2348
  "license": "ISC"
2349
  },
 
 
 
 
 
 
 
 
 
 
 
 
2350
  "node_modules/proxy-addr": {
2351
  "version": "2.0.7",
2352
  "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
 
2668
  "url": "https://github.com/sponsors/ljharb"
2669
  }
2670
  },
 
 
 
 
 
 
 
 
 
 
 
 
2671
  "node_modules/toidentifier": {
2672
  "version": "1.0.1",
2673
  "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
package.json CHANGED
@@ -8,13 +8,12 @@
8
  "start": "node server.js"
9
  },
10
  "engines": {
11
- "node": ">=18"
12
  },
13
  "dependencies": {
14
  "@babel/core": "^7.26.10",
15
  "@babel/preset-env": "^7.26.9",
16
  "express": "^4.19.2",
17
- "http-proxy-middleware": "^4.2.0",
18
  "regenerator-runtime": "^0.14.1"
19
  }
20
  }
 
8
  "start": "node server.js"
9
  },
10
  "engines": {
11
+ "node": ">=20"
12
  },
13
  "dependencies": {
14
  "@babel/core": "^7.26.10",
15
  "@babel/preset-env": "^7.26.9",
16
  "express": "^4.19.2",
 
17
  "regenerator-runtime": "^0.14.1"
18
  }
19
  }
server.js CHANGED
@@ -1,8 +1,8 @@
1
  const express = require('express')
2
  const fs = require('fs')
3
  const path = require('path')
 
4
  const babel = require('@babel/core')
5
- const { createProxyMiddleware } = require('http-proxy-middleware')
6
 
7
  const regeneratorRuntimeCode = fs.readFileSync(require.resolve('regenerator-runtime/runtime'), 'utf8')
8
 
@@ -124,6 +124,7 @@ function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator) {
124
  'allow[origin(__es5_base)]=1;' +
125
  'function proxyJs(u){var a=abs(u);var o=origin(a);if(__es5_active)allow[o]=1;allow[o]=1;if(allow[o]&&__es5_server){try{var testUrl=new URL(a);if(testUrl.protocol==="http:"||testUrl.protocol==="https:")return __es5_server + "/p?url=" + encodeURIComponent(a).replace(/%3A/gi, ":").replace(/%2F/gi, "/");}catch(e){}}return a;}' +
126
  'function proxyCss(u){var a=abs(u);var o=origin(a);if(__es5_active)allow[o]=1;if(allow[o]&&__es5_server)return __es5_server + "/s?url=" + encodeURIComponent(a).replace(/%3A/gi, ":").replace(/%2F/gi, "/");return a;}' +
 
127
  'function mapArr(items, fn){if(!items||!items.length)return items;for(var i=0;i<items.length;i++){items[i]=fn(items[i]);}return items;}' +
128
  'try{' +
129
  'if(window.Lampa&&Lampa.Utils){' +
@@ -151,6 +152,27 @@ function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator) {
151
  '}' +
152
  '}catch(e){}' +
153
  'try{if(window.__es5CssVarsApply)window.__es5CssVarsApply();}catch(e){}' +
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  'try{' +
155
  'var __mock_script = document.createElement("script");' +
156
  '__mock_script.src = __es5_base;' +
@@ -226,7 +248,7 @@ async function cssInline(url, depth, clientUA) {
226
 
227
  app.use((req, res, next) => {
228
  res.setHeader('Access-Control-Allow-Origin', '*');
229
- res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS');
230
  res.setHeader('Access-Control-Allow-Headers', '*');
231
  next();
232
  })
@@ -302,15 +324,78 @@ app.get('/p', async (req, res) => {
302
  }
303
  })
304
 
305
- // Проксируем весь остальной трафик на оригинальный сайт, чтобы обойти проблему с TLS сертификатами на старых ТВ
306
- // Таким образом, телик будет заходить по HTTP на твой сервер, а сервер будет тянуть HTTPS с tv.alcopa.cc
307
- app.use(createProxyMiddleware({
308
- target: 'https://tv.alcopa.cc',
309
- changeOrigin: true,
310
- onProxyRes: function (proxyRes, req, res) {
311
- proxyRes.headers['access-control-allow-origin'] = '*';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
  }
313
- }));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
 
315
  const port = Number(process.env.PORT || 7860)
316
  app.listen(port, () => {
 
1
  const express = require('express')
2
  const fs = require('fs')
3
  const path = require('path')
4
+ const { Readable } = require('stream')
5
  const babel = require('@babel/core')
 
6
 
7
  const regeneratorRuntimeCode = fs.readFileSync(require.resolve('regenerator-runtime/runtime'), 'utf8')
8
 
 
124
  'allow[origin(__es5_base)]=1;' +
125
  'function proxyJs(u){var a=abs(u);var o=origin(a);if(__es5_active)allow[o]=1;allow[o]=1;if(allow[o]&&__es5_server){try{var testUrl=new URL(a);if(testUrl.protocol==="http:"||testUrl.protocol==="https:")return __es5_server + "/p?url=" + encodeURIComponent(a).replace(/%3A/gi, ":").replace(/%2F/gi, "/");}catch(e){}}return a;}' +
126
  'function proxyCss(u){var a=abs(u);var o=origin(a);if(__es5_active)allow[o]=1;if(allow[o]&&__es5_server)return __es5_server + "/s?url=" + encodeURIComponent(a).replace(/%3A/gi, ":").replace(/%2F/gi, "/");return a;}' +
127
+ 'function proxyRaw(u){var a=abs(u);if(!/^https?:\\/\\//i.test(a))return u;if(__es5_server&&a.indexOf(__es5_server)===-1){return __es5_server+"/r?url="+encodeURIComponent(a).replace(/%3A/gi, ":").replace(/%2F/gi, "/");}return a;}' +
128
  'function mapArr(items, fn){if(!items||!items.length)return items;for(var i=0;i<items.length;i++){items[i]=fn(items[i]);}return items;}' +
129
  'try{' +
130
  'if(window.Lampa&&Lampa.Utils){' +
 
152
  '}' +
153
  '}catch(e){}' +
154
  'try{if(window.__es5CssVarsApply)window.__es5CssVarsApply();}catch(e){}' +
155
+ // Локальные (не глобальные!) fetch/XMLHttpRequest — видны только коду плагина,
156
+ // который выполняется ниже в этой же функции (transpiledCode вставлен прямо сюда).
157
+ // Остальная Лампа продолжает использовать настоящие window.fetch / window.XMLHttpRequest.
158
+ 'var _origFetch=window.fetch;' +
159
+ 'var fetch=function(input,init){' +
160
+ 'try{' +
161
+ 'if(typeof input==="string"){input=proxyRaw(input);}' +
162
+ 'else if(input&&input.url){input=new Request(proxyRaw(input.url),input);}' +
163
+ '}catch(e){}' +
164
+ 'return _origFetch.call(window,input,init);' +
165
+ '};' +
166
+ 'var _RealXHR=window.XMLHttpRequest;' +
167
+ 'var XMLHttpRequest=function(){' +
168
+ 'var xhr=new _RealXHR();' +
169
+ 'var origOpen=xhr.open;' +
170
+ 'xhr.open=function(method,u,async,user,pass){' +
171
+ 'try{u=proxyRaw(u);}catch(e){}' +
172
+ 'return origOpen.call(xhr,method,u,(async===undefined?true:async),user,pass);' +
173
+ '};' +
174
+ 'return xhr;' +
175
+ '};' +
176
  'try{' +
177
  'var __mock_script = document.createElement("script");' +
178
  '__mock_script.src = __es5_base;' +
 
248
 
249
  app.use((req, res, next) => {
250
  res.setHeader('Access-Control-Allow-Origin', '*');
251
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS');
252
  res.setHeader('Access-Control-Allow-Headers', '*');
253
  next();
254
  })
 
324
  }
325
  })
326
 
327
+ // Универсальный "сырой" прокси: любые данные как есть — JSON от API источника,
328
+ // картинки, m3u8/mp4-потоки и т.д. Без Babel и без лимита в MAX_BYTES, со стримингом
329
+ // и поддержкой Range (нужно для перемотки видео).
330
+ const RAW_METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS']
331
+ const REQ_HEADERS_PASS = ['range', 'if-range', 'accept', 'accept-language', 'content-type', 'referer', 'origin']
332
+ const RES_HEADERS_PASS = [
333
+ 'content-type', 'content-length', 'content-range', 'accept-ranges',
334
+ 'cache-control', 'expires', 'last-modified', 'etag'
335
+ ]
336
+
337
+ app.all('/r', async (req, res) => {
338
+ let rawUrl = req.query.url
339
+ if (rawUrl && (rawUrl.indexOf('%3A') !== -1 || rawUrl.indexOf('%3a') !== -1)) {
340
+ try { rawUrl = decodeURIComponent(rawUrl) } catch (e) {}
341
+ }
342
+
343
+ const source = normalizeUrl(rawUrl)
344
+ if (!source) return res.status(400).type('text/plain').send('Bad url')
345
+
346
+ const method = (req.method || 'GET').toUpperCase()
347
+ if (RAW_METHODS.indexOf(method) === -1) {
348
+ return res.status(405).type('text/plain').send('Method not allowed')
349
+ }
350
+ if (method === 'OPTIONS') return res.sendStatus(204)
351
+
352
+ const controller = new AbortController()
353
+ req.on('close', () => controller.abort())
354
+
355
+ const headers = {}
356
+ for (const h of REQ_HEADERS_PASS) {
357
+ if (req.headers[h]) headers[h] = req.headers[h]
358
  }
359
+ headers['user-agent'] = req.headers['user-agent']
360
+ ? req.headers['user-agent'] + ' Lampa'
361
+ : 'Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36 Lampa'
362
+
363
+ let body
364
+ if (method !== 'GET' && method !== 'HEAD') {
365
+ const chunks = []
366
+ for await (const chunk of req) chunks.push(chunk)
367
+ if (chunks.length) body = Buffer.concat(chunks)
368
+ }
369
+
370
+ try {
371
+ const upstream = await fetch(source, {
372
+ method,
373
+ headers,
374
+ body,
375
+ redirect: 'follow',
376
+ signal: controller.signal
377
+ })
378
+
379
+ res.status(upstream.status)
380
+ for (const h of RES_HEADERS_PASS) {
381
+ const v = upstream.headers.get(h)
382
+ if (v) res.setHeader(h, v)
383
+ }
384
+ res.setHeader('access-control-allow-origin', '*')
385
+
386
+ if (!upstream.body) return res.end()
387
+ Readable.fromWeb(upstream.body).pipe(res)
388
+ } catch (e) {
389
+ if (!res.headersSent) {
390
+ const code = e && e.status ? e.status : 502
391
+ res.status(code).type('text/plain').send('Proxy error')
392
+ } else {
393
+ try { res.end() } catch (e2) {}
394
+ }
395
+ }
396
+ })
397
+
398
+ app.options('*', (req, res) => res.sendStatus(204))
399
 
400
  const port = Number(process.env.PORT || 7860)
401
  app.listen(port, () => {