recycleactor commited on
Commit
322a047
·
verified ·
1 Parent(s): 0d73941

Upload server.js

Browse files
Files changed (1) hide show
  1. server.js +54 -40
server.js CHANGED
@@ -53,7 +53,7 @@ async function fetchText(url, timeoutMs, clientUA) {
53
  redirect: 'follow',
54
  signal: controller.signal,
55
  headers: {
56
- 'user-agent': clientUA ? (clientUA + ' Lampa') : 'Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36 Lampa'
57
  }
58
  })
59
 
@@ -81,7 +81,7 @@ async function fetchText(url, timeoutMs, clientUA) {
81
  }
82
  }
83
 
84
- function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator) {
85
  const safeServer = JSON.stringify(String(serverBase || ''))
86
  const safeBaseUrl = JSON.stringify(String(baseUrl || ''))
87
 
@@ -123,7 +123,7 @@ function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator) {
123
  'function origin(u){try{var a=document.createElement("a");a.href=u;return (a.protocol? a.protocol:"") + "//" + (a.host||"");}catch(e){return "";}}' +
124
  'var allow=window.__es5ProxyAllow||{};window.__es5ProxyAllow=allow;' +
125
  'allow[origin(__es5_base)]=1;' +
126
- '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;}' +
127
  '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;}' +
128
  '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;}' +
129
  '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;}' +
@@ -139,7 +139,7 @@ function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator) {
139
  'var origInsertBefore=Element.prototype.insertBefore;' +
140
  'function patchNode(node){' +
141
  'if(node&&node.tagName==="SCRIPT"&&node.src){' +
142
- 'var a=abs(node.src);var o2=origin(a);if(__es5_active)allow[o2]=1;allow[o2]=1;if(allow[o2]&&__es5_server&&node.src.indexOf(__es5_server)===-1){try{var testUrl=new URL(a);if(testUrl.protocol==="http:"||testUrl.protocol==="https:"){node.src=__es5_server+"/p?url="+encodeURIComponent(a).replace(/%3A/gi, ":").replace(/%2F/gi, "/");}}catch(e){}}' +
143
  '}' +
144
  '}' +
145
  'Element.prototype.appendChild=function(node){' +
@@ -152,10 +152,8 @@ function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator) {
152
  '};' +
153
  '}' +
154
  '}catch(e){}' +
155
- 'try{if(window.__es5CssVarsApply)window.__es5CssVarsApply();}catch(e){}' +
156
- // Локальные (не глобальные!) fetch/XMLHttpRequest — видны только коду плагина,
157
- // который выполняется ниже в этой же функции (transpiledCode вставлен прямо сюда).
158
- // Остальная Лампа продолжает использовать настоящие window.fetch / window.XMLHttpRequest.
159
  'var _origFetch=window.fetch;' +
160
  'var fetch=function(input,init){' +
161
  'try{' +
@@ -174,9 +172,6 @@ function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator) {
174
  '};' +
175
  'return xhr;' +
176
  '};' +
177
- // Локальный шим Lampa.Reguest — только для кода этого плагина.
178
- // network.silent(url,...) / network["native"](url,...) — основной способ,
179
- // которым плагины (в т.ч. этот) реально ходят за данными, минуя fetch/XHR напрямую.
180
  'try{' +
181
  'if(Lampa&&Lampa.Reguest){' +
182
  'var _RealReguest=Lampa.Reguest;' +
@@ -200,7 +195,8 @@ function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator) {
200
  'Lampa=Object.create(Lampa);' +
201
  'Lampa.Reguest=ReguestShim;' +
202
  '}' +
203
- '}catch(e){}' +
 
204
  'try{' +
205
  'var __mock_script = document.createElement("script");' +
206
  '__mock_script.src = __es5_base;' +
@@ -217,13 +213,15 @@ function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator) {
217
  'try { if(__orig_cs_desc) Object.defineProperty(document, "currentScript", __orig_cs_desc); else delete document.currentScript; } catch(e_cs2) {}' +
218
  '}' +
219
  '__es5_active=false;' +
220
- 'try{if(window.__es5CssVarsApply)window.__es5CssVarsApply();}catch(e){}' +
221
  '})();'
222
 
223
  const parts = []
224
- parts.push(fetchPolyfill)
225
- if (needRegenerator) parts.push(regeneratorRuntimeCode)
226
- parts.push(cssVarsPonyfill)
 
 
227
  parts.push(patchLoaders)
228
  return parts.join('\n')
229
  }
@@ -316,32 +314,41 @@ app.get('/p', async (req, res) => {
316
  const source = normalizeUrl(rawUrl)
317
  if (!source) return res.status(400).type('text/plain').send('Bad url')
318
 
 
 
 
319
  try {
320
  const { text } = await fetchText(source, 25_000, req.headers['user-agent'])
321
- const result = await babel.transformAsync(text, {
322
- babelrc: false,
323
- configFile: false,
324
- sourceType: 'script',
325
- compact: true,
326
- comments: false,
327
- presets: [
328
- [
329
- require('@babel/preset-env'),
330
- {
331
- targets: { chrome: '38' },
332
- bugfixes: true,
333
- loose: true,
334
- modules: false
335
- }
 
 
 
 
 
336
  ]
337
- ]
338
- })
339
-
340
- const code = (result && result.code) ? result.code : ''
341
- const needRegenerator = code.indexOf('regeneratorRuntime') !== -1
 
342
 
343
  const serverBase = getSelfBase(req)
344
- const out = jsWrapper(serverBase, source, code, needRegenerator)
345
 
346
  res.setHeader('content-type', 'application/javascript; charset=utf-8')
347
  res.setHeader('cache-control', 'public, max-age=600')
@@ -361,7 +368,8 @@ const RAW_METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS']
361
  const REQ_HEADERS_SKIP = new Set([
362
  'host', 'connection', 'content-length', 'accept-encoding',
363
  'x-forwarded-for', 'x-forwarded-proto', 'x-forwarded-host',
364
- 'cf-connecting-ip', 'cf-ray', 'cf-visitor', 'x-real-ip'
 
365
  ])
366
  const RES_HEADERS_PASS = [
367
  'content-type', 'content-length', 'content-range', 'accept-ranges',
@@ -393,8 +401,8 @@ app.all('/r', async (req, res) => {
393
  headers[h] = req.headers[h]
394
  }
395
  headers['user-agent'] = req.headers['user-agent']
396
- ? req.headers['user-agent'] + ' Lampa'
397
- : 'Mozilla/5.0 (Web0S; Linux/SmartTV) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36 Lampa'
398
 
399
  let body
400
  if (method !== 'GET' && method !== 'HEAD') {
@@ -414,6 +422,12 @@ app.all('/r', async (req, res) => {
414
 
415
  res.status(upstream.status)
416
  for (const h of RES_HEADERS_PASS) {
 
 
 
 
 
 
417
  const v = upstream.headers.get(h)
418
  if (v) res.setHeader(h, v)
419
  }
 
53
  redirect: 'follow',
54
  signal: controller.signal,
55
  headers: {
56
+ 'user-agent': clientUA ? clientUA : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
57
  }
58
  })
59
 
 
81
  }
82
  }
83
 
84
+ function jsWrapper(serverBase, baseUrl, transpiledCode, needRegenerator, useVpn, useEs5) {
85
  const safeServer = JSON.stringify(String(serverBase || ''))
86
  const safeBaseUrl = JSON.stringify(String(baseUrl || ''))
87
 
 
123
  'function origin(u){try{var a=document.createElement("a");a.href=u;return (a.protocol? a.protocol:"") + "//" + (a.host||"");}catch(e){return "";}}' +
124
  'var allow=window.__es5ProxyAllow||{};window.__es5ProxyAllow=allow;' +
125
  'allow[origin(__es5_base)]=1;' +
126
+ '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, "/") + "&es5=' + (useEs5?'1':'0') + '&vpn=' + (useVpn?'1':'0') + '";}catch(e){}}return a;}' +
127
  '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;}' +
128
  '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;}' +
129
  '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;}' +
 
139
  'var origInsertBefore=Element.prototype.insertBefore;' +
140
  'function patchNode(node){' +
141
  'if(node&&node.tagName==="SCRIPT"&&node.src){' +
142
+ 'var a=abs(node.src);var o2=origin(a);if(__es5_active)allow[o2]=1;allow[o2]=1;if(allow[o2]&&__es5_server&&node.src.indexOf(__es5_server)===-1){try{var testUrl=new URL(a);if(testUrl.protocol==="http:"||testUrl.protocol==="https:"){node.src=__es5_server+"/p?url="+encodeURIComponent(a).replace(/%3A/gi, ":").replace(/%2F/gi, "/")+"&es5=' + (useEs5?'1':'0') + '&vpn=' + (useVpn?'1':'0') + '";}}catch(e){}}' +
143
  '}' +
144
  '}' +
145
  'Element.prototype.appendChild=function(node){' +
 
152
  '};' +
153
  '}' +
154
  '}catch(e){}' +
155
+ (useEs5 ? 'try{if(window.__es5CssVarsApply)window.__es5CssVarsApply();}catch(e){}' : '') +
156
+ (useVpn ? (
 
 
157
  'var _origFetch=window.fetch;' +
158
  'var fetch=function(input,init){' +
159
  'try{' +
 
172
  '};' +
173
  'return xhr;' +
174
  '};' +
 
 
 
175
  'try{' +
176
  'if(Lampa&&Lampa.Reguest){' +
177
  'var _RealReguest=Lampa.Reguest;' +
 
195
  'Lampa=Object.create(Lampa);' +
196
  'Lampa.Reguest=ReguestShim;' +
197
  '}' +
198
+ '}catch(e){}'
199
+ ) : '') +
200
  'try{' +
201
  'var __mock_script = document.createElement("script");' +
202
  '__mock_script.src = __es5_base;' +
 
213
  'try { if(__orig_cs_desc) Object.defineProperty(document, "currentScript", __orig_cs_desc); else delete document.currentScript; } catch(e_cs2) {}' +
214
  '}' +
215
  '__es5_active=false;' +
216
+ (useEs5 ? 'try{if(window.__es5CssVarsApply)window.__es5CssVarsApply();}catch(e){}' : '') +
217
  '})();'
218
 
219
  const parts = []
220
+ if (useEs5) {
221
+ parts.push(fetchPolyfill)
222
+ if (needRegenerator) parts.push(regeneratorRuntimeCode)
223
+ parts.push(cssVarsPonyfill)
224
+ }
225
  parts.push(patchLoaders)
226
  return parts.join('\n')
227
  }
 
314
  const source = normalizeUrl(rawUrl)
315
  if (!source) return res.status(400).type('text/plain').send('Bad url')
316
 
317
+ const useEs5 = req.query.es5 !== '0';
318
+ const useVpn = req.query.vpn !== '0';
319
+
320
  try {
321
  const { text } = await fetchText(source, 25_000, req.headers['user-agent'])
322
+ let code = text;
323
+ let needRegenerator = false;
324
+
325
+ if (useEs5) {
326
+ const result = await babel.transformAsync(text, {
327
+ babelrc: false,
328
+ configFile: false,
329
+ sourceType: 'script',
330
+ compact: true,
331
+ comments: false,
332
+ presets: [
333
+ [
334
+ require('@babel/preset-env'),
335
+ {
336
+ targets: { chrome: '38' },
337
+ bugfixes: true,
338
+ loose: true,
339
+ modules: false
340
+ }
341
+ ]
342
  ]
343
+ })
344
+ if (result && result.code) {
345
+ code = result.code;
346
+ needRegenerator = code.indexOf('regeneratorRuntime') !== -1;
347
+ }
348
+ }
349
 
350
  const serverBase = getSelfBase(req)
351
+ const out = jsWrapper(serverBase, source, code, needRegenerator, useVpn, useEs5)
352
 
353
  res.setHeader('content-type', 'application/javascript; charset=utf-8')
354
  res.setHeader('cache-control', 'public, max-age=600')
 
368
  const REQ_HEADERS_SKIP = new Set([
369
  'host', 'connection', 'content-length', 'accept-encoding',
370
  'x-forwarded-for', 'x-forwarded-proto', 'x-forwarded-host',
371
+ 'cf-connecting-ip', 'cf-ray', 'cf-visitor', 'x-real-ip',
372
+ 'origin', 'referer'
373
  ])
374
  const RES_HEADERS_PASS = [
375
  'content-type', 'content-length', 'content-range', 'accept-ranges',
 
401
  headers[h] = req.headers[h]
402
  }
403
  headers['user-agent'] = req.headers['user-agent']
404
+ ? req.headers['user-agent']
405
+ : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
406
 
407
  let body
408
  if (method !== 'GET' && method !== 'HEAD') {
 
422
 
423
  res.status(upstream.status)
424
  for (const h of RES_HEADERS_PASS) {
425
+ if (h === 'content-length') {
426
+ const ct = upstream.headers.get('content-type') || '';
427
+ if (!ct.includes('video/') && !ct.includes('audio/') && !upstream.headers.has('content-range')) {
428
+ continue; // fetch decompresses gzip/br, so original content-length is invalid for text/json
429
+ }
430
+ }
431
  const v = upstream.headers.get(h)
432
  if (v) res.setHeader(h, v)
433
  }