Prechádzať zdrojové kódy

Merge branch 'dev' into demo

zjcqoo 6 rokov pred
rodič
commit
6cc0a56d25
6 zmenil súbory, kde vykonal 167 pridanie a 43 odobranie
  1. 3 1
      README.md
  2. 2 0
      allowed-sites.conf
  3. 55 1
      cf-worker/README.md
  4. 73 25
      cf-worker/index.js
  5. 13 13
      upload.sh
  6. 21 3
      www.conf

+ 3 - 1
README.md

@@ -1,6 +1,8 @@
 
 # 更新
 
+* 2019-06-22 [cfworker 无服务器版](cf-worker) 发布,长期使用演示服务的请使用该版本。
+
 * 2019-06-11 前端脚本调整,首页可离线访问(如果长时间加载中,尝试多刷新几次或者隐身模式访问)
 
 * 2019-05-30 更新 cfworker,对 ytb 视频进行了优化(推荐选 1080p+,不会增加服务器压力)
@@ -37,7 +39,7 @@ Fork 本项目,进入 `gh-pages` 分支,编辑 `conf.js` 文件:
 
 * 默认节点(`node_default` 字段,指定节点 id)
 
-访问 `https://用户名.github.io/jsproxy/index.html` 预览。
+访问 `https://用户名.github.io/jsproxy` 预览。
 
 GitHub 支持[自定义域名](https://help.github.com/en/articles/using-a-custom-domain-with-github-pages)。也可以将文件发布到自己的 Web 服务器上。
 

+ 2 - 0
allowed-sites.conf

@@ -23,5 +23,7 @@ https://360safe.tk                '360';
 # ~ 开头为正则匹配,此处允许 github.io 所有子站点
 ~^https://([\w-]+)\.github\.io$   'gh-$1';
 
+~^https://node-aliyun-hk-\d\.etherdream\.com:8443$            'eth.com';
+
 # 允许任何站点使用
 # ~(.*)                             '$1';

+ 55 - 1
cf-worker/README.md

@@ -1 +1,55 @@
-https://cloudflareworkers.com/
+使用 CloudFlare Worker 免费部署
+
+
+# 简介
+
+`CloudFlare Worker` 是 CloudFlare 的边缘计算服务。开发者可通过 JavaScript 对 CDN 进行编程,从而能灵活处理 HTTP 请求。这使得很多任务可在 CDN 上完成,无需自己的服务器参与。
+
+
+# 部署
+
+首页:https://workers.cloudflare.com
+
+注册,登陆,`Start building`,取一个子域名,`Create a Worker`。
+
+复制 [index.js](https://raw.githubusercontent.com/EtherDream/jsproxy/master/cf-worker/index.js) 到左侧代码框,`Save and deploy`。如果正常,右侧应显示首页。
+
+收藏地址框中的 `https://xxxx.子域名.workers.dev`,以后可直接访问。
+
+
+# 计费
+
+后退到 `overview` 页面可参看使用情况。免费版每天有 10 万次免费请求,对于个人通常足够。
+
+如果不够用,可注册多个 Worker,在 `conf.js` 中配置多线路负载均衡。或者升级到 $5 的高级版本,每月可用 1000 万次请求(超出部分 $0.5/百万次请求)。
+
+如果远不够用,建议和服务器组合使用。因为 cfworker 是按请求次数计费的,所以小文件更适合通过服务器代理,大文件走 cfworker 才合算。可参考下面的 `加速功能`。
+
+
+# 修改配置
+
+默认情况下,静态资源从 `https://zjcqoo.github.io` 反向代理,可通过代码中 `ASSET_URL` 配置,从而可使用自定义的 `conf.js` 配置。
+
+
+# 加速功能
+
+如果你已有服务器,也可通过 CloudFlare Worker 分担大文件的代理。
+
+前端修改:`conf.js` 的 `cfworker` 节点 `lines` 配置。
+
+后端修改:`lua/http-enc-res-hdr.lua` 的 [114-116 行](https://github.com/EtherDream/jsproxy/blob/master/lua/http-enc-res-hdr.lua#L114-L116) 注释打开,重启服务生效。
+
+可在 [84行](https://github.com/EtherDream/jsproxy/blob/master/lua/http-enc-res-hdr.lua#L84) 处修改大于多少字节的静态资源走加速。
+
+该功能目前还在实验中,有问题或者更好的思路可交流。
+
+(推荐下行流量免费且不限速的服务器,可节省大量费用)
+
+
+# 存在问题
+
+* WebSocket 代理尚未实现
+
+* 外链限制尚未实现
+
+* 未充分测试,以后再完善

+ 73 - 25
cf-worker/index.js

@@ -1,10 +1,13 @@
+'use strict'
+
 /**
- * jsproxy cfworker api
- * https://github.com/EtherDream/jsproxy/
+ * static files (404.html, sw.js, conf.js)
  */
-'use strict'
+const ASSET_URL = 'https://zjcqoo.github.io'
+
+const JS_VER = 8
+const MAX_RETRY = 1
 
-const JS_VER = 4
 
 const PREFLIGHT_INIT = {
   status: 204,
@@ -16,9 +19,36 @@ const PREFLIGHT_INIT = {
   }),
 }
 
+/**
+ * @param {string} message
+ * @param {number} status
+ * @param {any} headers
+ */
+function makeRes(message, status = 200, headers = {}) {
+  headers['cache-control'] = 'no-cache'
+  return new Response(message, {status, headers})
+}
+
 
 addEventListener('fetch', e => {
-  const ret = handler(e.request)
+  const req = e.request
+  const urlStr = req.url
+  const urlObj = new URL(urlStr)
+  let ret
+
+
+  switch (urlObj.pathname) {
+  case '/http':
+    ret = handler(req)
+    break
+  case '/works':
+    ret = makeRes('it works')
+    break
+  default:
+    // static files
+    ret = fetch(ASSET_URL + urlObj.pathname)
+    break
+  }
   e.respondWith(ret)
 })
 
@@ -87,6 +117,9 @@ async function handler(req) {
       reqHdrNew.set(k, v)
     }
   }
+  if (!urlObj) {
+    return makeRes('missing url param', 403)
+  }
   const reqInit = {
     method: req.method,
     headers: reqHdrNew,
@@ -142,34 +175,49 @@ async function proxy(urlObj, reqInit, acehOld, rawLen, retryTimes) {
     resHdrNew.set('--t', '1')
   }
 
-  resHdrNew.set('access-control-expose-headers', expose)
-  resHdrNew.set('access-control-allow-origin', '*')
-  resHdrNew.set('vary', vary)
-  resHdrNew.set('--s', res.status)
-
   // verify
-  const newLen = resHdrOld.get('content-length') || ''
-  const badLen = (rawLen !== newLen)
+  if (rawLen) {
+    const newLen = resHdrOld.get('content-length') || ''
+    const badLen = (rawLen !== newLen)
 
-  let status = 200
-  let body = res.body
-
-  if (badLen) {
-    if (retryTimes < 1) {
-      urlObj = await parseYtVideoRedir(urlObj, newLen, res)
-      if (urlObj) {
-        return proxy(urlObj, reqInit, acehOld, rawLen, retryTimes + 1)
+    if (badLen) {
+      if (retryTimes < MAX_RETRY) {
+        urlObj = await parseYtVideoRedir(urlObj, newLen, res)
+        if (urlObj) {
+          return proxy(urlObj, reqInit, acehOld, rawLen, retryTimes + 1)
+        }
       }
+      return makeRes(`error`, 400, {
+        '--error': 'bad len:' + newLen
+      })
+    }
+
+    if (retryTimes > 1) {
+      resHdrNew.set('--retry', retryTimes)
     }
-    status = 400
-    body = `bad len (old: ${rawLen} new: ${newLen})`
-    resHdrNew.set('cache-control', 'no-cache')
   }
 
-  resHdrNew.set('--retry', retryTimes)
+  let status = res.status
+
+  resHdrNew.set('access-control-expose-headers', expose)
+  resHdrNew.set('access-control-allow-origin', '*')
+  resHdrNew.set('vary', vary)
+  resHdrNew.set('--s', status)
   resHdrNew.set('--ver', JS_VER)
 
-  return new Response(body, {
+  resHdrNew.delete('content-security-policy')
+  resHdrNew.delete('content-security-policy-report-only')
+
+  if (status === 301 ||
+      status === 302 ||
+      status === 303 ||
+      status === 307 ||
+      status === 308
+  ) {
+    status = status + 10
+  }
+
+  return new Response(res.body, {
     status,
     headers: resHdrNew,
   })

+ 13 - 13
upload.sh

@@ -4,29 +4,29 @@
 HOST=etherdream.com
 NODE=(
   aliyun-hk-0
-  # aliyun-hk-1
   aliyun-hk-2
   aliyun-hk-3
   aliyun-hk-4
   aliyun-sg
 )
 for v in ${NODE[@]}; do
-  # echo "$v upload ..."
-  # rsync . jsproxy@$v.$HOST:server \
-  #   -a \
-  #   --exclude='nginx/cache/*' \
-  #   --exclude='nginx/logs/*'
+  echo "$v upload ..."
+  rsync . jsproxy@$v.$HOST:server \
+    -a \
+    --exclude='nginx/cache/*' \
+    --exclude='nginx/logs/*'
 
 
-  # echo "$v reload nginx ..."
-  # ssh jsproxy@$v.$HOST "./server/run.sh reload"
+  echo "$v reload nginx ..."
+  ssh jsproxy@$v.$HOST "./server/run.sh reload"
 
 
-  echo "$v reload svc.sh"
-  ssh jsproxy@$v.$HOST << EOF
-pkill -f svc.sh
-./server/log-svc/svc.sh &
-EOF
+#   echo "$v reload svc.sh"
+#   ssh jsproxy@$v.$HOST << EOF
+# pkill -f svc.sh
+# ./server/log-svc/svc.sh &
+# EOF
+
 
   # echo "$v update www"
   # ssh jsproxy@$v.$HOST "cd server/www && git pull"

+ 21 - 3
www.conf

@@ -16,13 +16,31 @@ error_page            404 = /404.html;
 location = /404.html {
   internal;
   root                ../www;
-}
 
-location = / {
-  rewrite             ^ /404.html;
+  # http 重定向到 https(忽略 localhost 或 IP 访问)
+  access_by_lua_block {
+    if ngx.var.scheme == 'https' then
+      return
+    end
+    local host = ngx.var.host
+    if host == 'localhost' then
+      return
+    end
+    if ngx.re.match(host, [[^\d+\.\d+\.\d+\.\d+$]]) then
+      return
+    end
+    local url = host .. ':8443' .. ngx.var.request_uri
+    ngx.redirect('https://' .. url, 301)
+  }
+
+  # 永久重定向申请: https://hstspreload.org/
+  more_set_headers
+    'strict-transport-security: max-age=99999999; includeSubDomains; preload'
+  ;
 }
 
 location / {
   access_log          logs/access.log log_www buffer=64k flush=1s;
   root                ../www;
+  index               404.html;
 }