全球主机交流论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

IP归属甄别会员请立即修改密码
查看: 592|回复: 5
打印 上一主题 下一主题

用免费的阿里云ESA流畅访问Stack Overflow --查bug用

[复制链接]
跳转到指定楼层
1#
发表于 2025-7-24 15:00:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 268296 于 2025-7-24 15:18 编辑

博客上的教程地址: https://www.cveoy.top/t/topic/qFMo

中国站( aliyun.com )免费领ESA: http://s.tb.cn/e6.0FuRjs  (官方链接非aff)
国际站( alibabacloud.com )免费领ESA: http://s.tb.cn/e6.0vy7ie (官方链接非aff)

https://esa.console.aliyun.com/edge/function/list 创建一个边缘函数
代码换为以下代码
  1. 'use strict'

  2. const ASSET_URL = 'https://www.cveoy.top/'
  3. const JS_VER = 10
  4. const MAX_RETRY = 1

  5. /** [url=home.php?mod=space&uid=26679]@Type[/url] {RequestInit} */
  6. const PREFLIGHT_INIT = {
  7.   status: 204,
  8.   headers: new Headers({
  9.     'access-control-allow-origin': '*',
  10.     'access-control-allow-methods': 'GET,POST,PUT,PATCH,TRACE,DELETE,HEAD,OPTIONS',
  11.     'access-control-max-age': '1728000',
  12.   }),
  13. }

  14. /** 工具函数:生成响应 */
  15. function makeRes(body, status = 200, headers = {}) {
  16.   headers['--ver'] = JS_VER
  17.   headers['access-control-allow-origin'] = '*'
  18.   return new Response(body, { status, headers })
  19. }

  20. /** 工具函数:解析 URL */
  21. function newUrl(urlStr) {
  22.   try {
  23.     return new URL(urlStr)
  24.   } catch (err) {
  25.     return null
  26.   }
  27. }

  28. /** 入口函数:模块方式导出 */
  29. export default {
  30.   async fetch(req, env, ctx) {
  31.     return fetchHandler(req).catch(err =>
  32.       makeRes('cfworker error:\n' + err.stack, 502)
  33.     )
  34.   }
  35. }

  36. /** 主处理函数 */
  37. async function fetchHandler(req) {
  38.   const urlStr = req.url
  39.   const urlObj = new URL(urlStr)
  40.   const path = urlObj.href.substr(urlObj.origin.length)

  41.   // 强制 HTTPS 跳转
  42.   if (urlObj.protocol === 'http:') {
  43.     urlObj.protocol = 'https:'
  44.     return makeRes('', 301, {
  45.       'strict-transport-security': 'max-age=99999999; includeSubDomains; preload',
  46.       'location': urlObj.href,
  47.     })
  48.   }

  49.   // 代理请求
  50.   if (path.startsWith('/http/')) {
  51.     return httpHandler(req, path.substr(6))
  52.   }

  53.   // 特殊路径处理
  54.   switch (path) {
  55.     case '/http':
  56.       return makeRes('请更新到最新版本!')
  57.     case '/ws':
  58.       return makeRes('not support', 400)
  59.     case '/works':
  60.       return makeRes('it works')
  61.     default:
  62.       return fetch(ASSET_URL + path)
  63.   }
  64. }

  65. /** HTTP 代理处理逻辑 */
  66. function httpHandler(req, pathname) {
  67.   const reqHdrRaw = req.headers
  68.   if (reqHdrRaw.has('x-jsproxy')) {
  69.     return Response.error()
  70.   }

  71.   if (
  72.     req.method === 'OPTIONS' &&
  73.     reqHdrRaw.has('access-control-request-headers')
  74.   ) {
  75.     return new Response(null, PREFLIGHT_INIT)
  76.   }

  77.   let acehOld = false
  78.   let rawSvr = ''
  79.   let rawLen = ''
  80.   let rawEtag = ''

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

  83.   const refer = reqHdrNew.get('referer') || ''
  84.   const query = refer.includes('?') ? refer.split('?')[1] : ''
  85.   if (!query) {
  86.     return makeRes('missing params', 403)
  87.   }

  88.   const param = new URLSearchParams(query)
  89.   for (const [k, v] of param.entries()) {
  90.     if (k.startsWith('--')) {
  91.       switch (k.slice(2)) {
  92.         case 'aceh':
  93.           acehOld = true
  94.           break
  95.         case 'raw-info':
  96.           [rawSvr, rawLen, rawEtag] = v.split('|')
  97.           break
  98.       }
  99.     } else {
  100.       if (v) {
  101.         reqHdrNew.set(k, v)
  102.       } else {
  103.         reqHdrNew.delete(k)
  104.       }
  105.     }
  106.   }

  107.   if (!param.has('referer')) {
  108.     reqHdrNew.delete('referer')
  109.   }

  110.   const urlStr = pathname.replace(/^(https?):\/+/, '$1://')
  111.   const urlObj = newUrl(urlStr)
  112.   if (!urlObj) {
  113.     return makeRes('invalid proxy url: ' + urlStr, 403)
  114.   }

  115.   const reqInit = {
  116.     method: req.method,
  117.     headers: reqHdrNew,
  118.     redirect: 'manual',
  119.     body: req.method === 'POST' ? req.body : undefined,
  120.   }

  121.   return proxy(urlObj, reqInit, acehOld, rawLen, 0)
  122. }

  123. /** 发起代理请求 */
  124. async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
  125.   const res = await fetch(urlObj.href, reqInit)
  126.   const resHdrOld = res.headers
  127.   const resHdrNew = new Headers(resHdrOld)

  128.   let expose = '*'

  129.   for (const [k, v] of resHdrOld.entries()) {
  130.     if (
  131.       k === 'access-control-allow-origin' ||
  132.       k === 'access-control-expose-headers' ||
  133.       k === 'location' ||
  134.       k === 'set-cookie'
  135.     ) {
  136.       const x = '--' + k
  137.       resHdrNew.set(x, v)
  138.       if (acehOld) {
  139.         expose += ',' + x
  140.       }
  141.       resHdrNew.delete(k)
  142.     } else if (
  143.       acehOld &&
  144.       !['cache-control', 'content-language', 'content-type', 'expires', 'last-modified', 'pragma'].includes(k)
  145.     ) {
  146.       expose += ',' + k
  147.     }
  148.   }

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

  153.   if (rawLen) {
  154.     const newLen = resHdrOld.get('content-length') || ''
  155.     const badLen = rawLen !== newLen

  156.     if (badLen) {
  157.       if (retryTimes < MAX_RETRY) {
  158.         const newUrlObj = await parseYtVideoRedir(urlObj, newLen, res)
  159.         if (newUrlObj) {
  160.           return proxy(newUrlObj, reqInit, acehOld, rawLen, retryTimes + 1)
  161.         }
  162.       }

  163.       return makeRes(res.body, 400, {
  164.         '--error': `bad len: ${newLen}, expect: ${rawLen}`,
  165.         'access-control-expose-headers': '--error',
  166.       })
  167.     }

  168.     if (retryTimes > 1) {
  169.       resHdrNew.set('--retry', retryTimes)
  170.     }
  171.   }

  172.   let status = res.status
  173.   resHdrNew.set('access-control-expose-headers', expose)
  174.   resHdrNew.set('access-control-allow-origin', '*')
  175.   resHdrNew.set('--s', status)
  176.   resHdrNew.set('--ver', JS_VER)

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

  180.   if ([301, 302, 303, 307, 308].includes(status)) {
  181.     status += 10
  182.   }

  183.   return new Response(res.body, {
  184.     status,
  185.     headers: resHdrNew,
  186.   })
  187. }

  188. /** 判断是否为 有图比 视频 URL */
  189. function isYtUrl(urlObj) {
  190.   return (
  191.     urlObj.host.endsWith('.googlevideo.com') &&
  192.     urlObj.pathname.startsWith('/videoplayback')
  193.   )
  194. }

  195. /** 处理 有图比 视频跳转解析 */
  196. async function parseYtVideoRedir(urlObj, newLen, res) {
  197.   if (parseInt(newLen) > 2000 || !isYtUrl(urlObj)) {
  198.     return null
  199.   }
  200.   try {
  201.     const data = await res.text()
  202.     const newUrl = newUrl(data)
  203.     return isYtUrl(newUrl) ? newUrl : null
  204.   } catch {
  205.     return null
  206.   }
  207. }
复制代码

然后点击快速发布,再点击触发器绑定你的域名。搞定
这个速度正常上网是够用了

此教程仅供学习使用,使用者需要自行承担相关责任。
推荐
发表于 2025-7-24 15:10:20 | 只看该作者
你不是入籍新加坡吗,还需要翻?
3#
发表于 2025-7-24 15:10:21 来自手机 | 只看该作者
我只能说666
4#
发表于 2025-7-26 10:26:11 | 只看该作者
5#
发表于 2025-7-26 10:32:18 | 只看该作者
国际站免费,套路云这双标玩得。
https://www.alibabacloud.com/help/zh/edge-security-acceleration/esa/product-overview/how-to-get-esa-for-free
6#
发表于 2025-7-26 13:55:05 | 只看该作者
创建的时候选择哪个呢?里面的代码不能改
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|全球主机交流论坛

GMT+8, 2025-10-30 05:25 , Processed in 0.061058 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表