Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

这个在线代理不能用了!出现了403Access Denied! You are not authorized to access this GitHub Pages site.!跪求新的代码 #305

Open
lvfeijun opened this issue Dec 16, 2020 · 18 comments

Comments

@lvfeijun
Copy link

'use strict'

/**
*/
const ASSET_URL = 'https://etherdream.github.io/jsproxy'

const JS_VER = 10
const MAX_RETRY = 1

/** @type {RequestInit} /
const PREFLIGHT_INIT = {
status: 204,
headers: new Headers({
'access-control-allow-origin': '
',
'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS',
'access-control-max-age': '1728000',
}),
}

/**

  • @param {any} body
  • @param {number} status
  • @param {Object<string, string>} headers
    /
    function makeRes(body, status = 200, headers = {}) {
    headers['--ver'] = JS_VER
    headers['access-control-allow-origin'] = '
    '
    return new Response(body, {status, headers})
    }

/**

  • @param {string} urlStr
    */
    function newUrl(urlStr) {
    try {
    return new URL(urlStr)
    } catch (err) {
    return null
    }
    }

addEventListener('fetch', e => {
const ret = fetchHandler(e)
.catch(err => makeRes('cfworker error:\n' + err.stack, 502))
e.respondWith(ret)
})

/**

  • @param {FetchEvent} e
    */
    async function fetchHandler(e) {
    const req = e.request
    const urlStr = req.url
    const urlObj = new URL(urlStr)
    const path = urlObj.href.substr(urlObj.origin.length)

if (urlObj.protocol === 'http:') {
urlObj.protocol = 'https:'
return makeRes('', 301, {
'strict-transport-security': 'max-age=99999999; includeSubDomains; preload',
'location': urlObj.href,
})
}

if (path.startsWith('/http/')) {
return httpHandler(req, path.substr(6))
}

switch (path) {
case '/http':
return makeRes('请更新 cfworker 到最新版本!')
case '/ws':
return makeRes('not support', 400)
case '/works':
return makeRes('it works')
default:
// static files
return fetch(ASSET_URL + path)
}
}

/**

  • @param {Request} req
  • @param {string} pathname
    */
    function httpHandler(req, pathname) {
    const reqHdrRaw = req.headers
    if (reqHdrRaw.has('x-jsproxy')) {
    return Response.error()
    }

// preflight
if (req.method === 'OPTIONS' &&
reqHdrRaw.has('access-control-request-headers')
) {
return new Response(null, PREFLIGHT_INIT)
}

let acehOld = false
let rawSvr = ''
let rawLen = ''
let rawEtag = ''

const reqHdrNew = new Headers(reqHdrRaw)
reqHdrNew.set('x-jsproxy', '1')

// 此处逻辑和 http-dec-req-hdr.lua 大致相同
// https://github.com/EtherDream/jsproxy/blob/master/lua/http-dec-req-hdr.lua
const refer = reqHdrNew.get('referer')
const query = refer.substr(refer.indexOf('?') + 1)
if (!query) {
return makeRes('missing params', 403)
}
const param = new URLSearchParams(query)

for (const [k, v] of Object.entries(param)) {
if (k.substr(0, 2) === '--') {
// 系统信息
switch (k.substr(2)) {
case 'aceh':
acehOld = true
break
case 'raw-info':
[rawSvr, rawLen, rawEtag] = v.split('|')
break
}
} else {
// 还原 HTTP 请求头
if (v) {
reqHdrNew.set(k, v)
} else {
reqHdrNew.delete(k)
}
}
}
if (!param.has('referer')) {
reqHdrNew.delete('referer')
}

// cfworker 会把路径中的 // 合并成 /
const urlStr = pathname.replace(/^(https?):/+/, '$1://')
const urlObj = newUrl(urlStr)
if (!urlObj) {
return makeRes('invalid proxy url: ' + urlStr, 403)
}

/** @type {RequestInit} */
const reqInit = {
method: req.method,
headers: reqHdrNew,
redirect: 'manual',
}
if (req.method === 'POST') {
reqInit.body = req.body
}
return proxy(urlObj, reqInit, acehOld, rawLen, 0)
}

/**
*

  • @param {URL} urlObj
  • @param {RequestInit} reqInit
  • @param {number} retryTimes
    */
    async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
    const res = await fetch(urlObj.href, reqInit)
    const resHdrOld = res.headers
    const resHdrNew = new Headers(resHdrOld)

let expose = '*'

for (const [k, v] of resHdrOld.entries()) {
if (k === 'access-control-allow-origin' ||
k === 'access-control-expose-headers' ||
k === 'location' ||
k === 'set-cookie'
) {
const x = '--' + k
resHdrNew.set(x, v)
if (acehOld) {
expose = expose + ',' + x
}
resHdrNew.delete(k)
}
else if (acehOld &&
k !== 'cache-control' &&
k !== 'content-language' &&
k !== 'content-type' &&
k !== 'expires' &&
k !== 'last-modified' &&
k !== 'pragma'
) {
expose = expose + ',' + k
}
}

if (acehOld) {
expose = expose + ',--s'
resHdrNew.set('--t', '1')
}

// verify
if (rawLen) {
const newLen = resHdrOld.get('content-length') || ''
const badLen = (rawLen !== newLen)

if (badLen) {
  if (retryTimes < MAX_RETRY) {
    urlObj = await parseYtVideoRedir(urlObj, newLen, res)
    if (urlObj) {
      return proxy(urlObj, reqInit, acehOld, rawLen, retryTimes + 1)
    }
  }
  return makeRes(res.body, 400, {
    '--error': `bad len: ${newLen}, except: ${rawLen}`,
    'access-control-expose-headers': '--error',
  })
}

if (retryTimes > 1) {
  resHdrNew.set('--retry', retryTimes)
}

}

let status = res.status

resHdrNew.set('access-control-expose-headers', expose)
resHdrNew.set('access-control-allow-origin', '*')
resHdrNew.set('--s', status)
resHdrNew.set('--ver', JS_VER)

resHdrNew.delete('content-security-policy')
resHdrNew.delete('content-security-policy-report-only')
resHdrNew.delete('clear-site-data')

if (status === 301 ||
status === 302 ||
status === 303 ||
status === 307 ||
status === 308
) {
status = status + 10
}

return new Response(res.body, {
status,
headers: resHdrNew,
})
}

/**

  • @param {URL} urlObj
    */
    function isYtUrl(urlObj) {
    return (
    urlObj.host.endsWith('.googlevideo.com') &&
    urlObj.pathname.startsWith('/videoplayback')
    )
    }

/**

  • @param {URL} urlObj
  • @param {number} newLen
  • @param {Response} res
    */
    async function parseYtVideoRedir(urlObj, newLen, res) {
    if (newLen > 2000) {
    return null
    }
    if (!isYtUrl(urlObj)) {
    return null
    }
    try {
    const data = await res.text()
    urlObj = new URL(data)
    } catch (err) {
    return null
    }
    if (!isYtUrl(urlObj)) {
    return null
    }
    return urlObj
@lvfeijun
Copy link
Author

Uploading RGEY~Q5SY}1684N)R7R{60I.png…

@Borber
Copy link

Borber commented Jan 11, 2021

自己不会弄吧?这目前吊打市面上的js proxy ,去耍我的https://js.zmirror.xyz

可以分享一下你的站的源碼嗎? 很喜歡

@Yandexkg
Copy link

邮件地址给我

@Borber
Copy link

Borber commented Jan 14, 2021

邮件地址给我

borber.drum@gmail.com 谢谢大佬

@fengzhao
Copy link

fengzhao commented Mar 4, 2021

邮件地址给我

大佬,求个代码 fengzhao1124@gmail.com

@RSSYLY
Copy link

RSSYLY commented Mar 5, 2021

邮件地址给我

大佬,也求个代码😏 olddriverwang@gmail.com

@zyan66
Copy link

zyan66 commented Mar 7, 2021

邮件地址给我

求大佬发一下2085883961@qq.com 谢谢

@lksin
Copy link

lksin commented Mar 27, 2021

邮件地址给我

大佬,跪求代码 2517871772@qq.com,万分感谢

@yingxueziqi
Copy link

自己不会弄吧?这目前吊打市面的js proxy,去耍我的https://js.zmirror.xyz

@yingxueziqi
Copy link

cxkjntm007@gmail.com 大佬求一个

@Letget
Copy link

Letget commented Jun 1, 2021

邮件地址给我

2471507514@qq.com
感谢大佬求一个

@solitudealma
Copy link

邮件地址给我

能发一下代码吗,谢谢
2241141629yt@gmail.com

@jimmyrogue
Copy link

邮件地址给我

@Yandexkg 大佬求源码 tliang92@gmail.com

@Letget
Copy link

Letget commented Sep 26, 2021

邮件地址给我

求源码学习参考,谢谢大佬

letgptten@gmail.com

@Smart-Chou
Copy link

邮件地址给我

求源码学习参考,感谢大佬!
ChouCong912@gmail.com

@kanomahoro
Copy link

邮件地址给我

大佬,求一份代码,十分感谢!!623409723@qq.com

@bigshezhang
Copy link

邮件地址给我

求源码学习一下,感谢大佬!!!bigshezhang@gmail.com

@Xiao-Chuzhang
Copy link

邮件地址给我

大佬我也求一个 colime@qq.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests