CloudFlare Workers

Posted by API Caller on June 9, 2019

想想怎么滥用

看到 利用 CloudFlare workers + Github 实现简易动态博客 知道的, 了解了下, 专业名词叫边缘计算, 目的是为了利用靠用户侧的分布式资源进行云计算. 试了下, 记录一下.

在 cloudflare 激活一下就可以从面板进入, 会先让设置一个 __.workers.dev 的域名, 用来发布 workers, 且域名不能更改.

新建 workers 之后会分配一个随机的名称, 然后自动进入到在线编辑器, 编辑器的界面类似于 Chrome DevTools.

使用的是 v8 engine, 支持 js 是不用说了, 也已经支持 wasm, 这点很不错, 可以用 go 了.

官方给了个 demo:

1
2
3
4
5
6
7
8
9
10
11
12
addEventListener('fetch', e => {
  e.respondWith(proxy(e.request))
})

/**
 * @param {Request} req
 */
async function proxy(req) {
  const urlObj = new URL(req.url)
  const targetUrl = urlObj.searchParams.get('url')
  return fetch(targetUrl)
}

其实这就实现了代理, 比如 https://xxxx.yyy.workers.dev?url=http://www.google.com/dl/release2/chrome/AO70FMhxmobc_77.0.3819.0/77.0.3819.0_chrome_installer.exe 就可以来免代理下载文件…电信试了一下居然有 4M/s

workers.js 如果写得完善点, 似乎可以当代理来用了.

Wrangler

以一个 proxy 举例

https://a.downloader.workers.dev/

  • 用 wrangler 生成 ts 模版
1
2
3
4
5
6
7
# https://developers.cloudflare.com/workers/templates/

wrangler generate a https://github.com/EverlastingBugstopper/worker-typescript-template

cd a

wrangler build
  • 配置 wrangler.toml
1
2
3
4
5
6
name = "a"
type = "webpack"
zone_id = ""
private = false
account_id = "这里填写 account_id"
route = "downloader.workers.dev"
  • 配置环境变量
1
2
export CF_API_KEY=这里填写 API KEY
export CF_EMAIL=这里填写用户邮箱
  • 配置压缩
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const TerserPlugin = require('terser-webpack-plugin');

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        parallel: true,
        terserOptions: {
          ecma: 6,
        },
      }),
    ],
  },
  ...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
function MD2HTML(title: string, markdown: string): string {
    return `<!DOCTYPE html><html lang="zh"><head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible"content="IE=edge"/><meta http-equiv="Cache-Control"content="no-siteapp"/><meta name="renderer"content="webkit"/><meta name="viewport"content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><title>${title}</title><link rel="stylesheet"href="//cdn.jsdelivr.net/gh/pandao/[email protected]/examples/css/style.css"/><link rel="stylesheet"href="//cdn.jsdelivr.net/gh/pandao/[email protected]/css/editormd.preview.css"/><!--<link rel="shortcut icon"href="https://pandao.github.io/editor.md/favicon.ico"type="image/x-icon"/>--><style>.editormd-html-preview{width:90%;margin:0 auto}</style></head><body><div id="layout"><div id="test-editormd-view"><!--<textarea style="display:none;"name="test-editormd-markdown-doc">###Hello world!</textarea>--></div></div><script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/examples/js/jquery.min.js"></script><script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/marked.min.js"></script><script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/prettify.min.js"></script><script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/raphael.min.js"></script><script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/underscore.min.js"></script><script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/sequence-diagram.min.js"></script><script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/flowchart.min.js"></script><script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/jquery.flowchart.min.js"></script><script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/editormd.js"></script><script type="text/javascript">$(function(){var testEditormdView=editormd.markdownToHTML("test-editormd-view",{markdown:unescape('${escape(markdown)}'),htmlDecode:"style,script,iframe",tocm:true,emoji:true,taskList:true,tex:true,flowChart:true,sequenceDiagram:true,})});</script></body></html>`
    //   return `
    //   <!DOCTYPE html>
    // <html lang="zh">

    // <head>
    //     <meta charset="utf-8" />
    //     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    //     <meta http-equiv="Cache-Control" content="no-siteapp" />
    //     <meta name="renderer" content="webkit" />
    //     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
    //     <title>${title}</title>
    //     <link rel="stylesheet" href="//cdn.jsdelivr.net/gh/pandao/[email protected]/examples/css/style.css" />
    //     <link rel="stylesheet" href="//cdn.jsdelivr.net/gh/pandao/[email protected]/css/editormd.preview.css" />
    //     <!-- <link rel="shortcut icon" href="https://pandao.github.io/editor.md/favicon.ico" type="image/x-icon" /> -->
    //     <style>
    //         .editormd-html-preview {
    //             width: 90%;
    //             margin: 0 auto;
    //         }
    //     </style>
    // </head>

    // <body>
    //     <div id="layout">
    //         <div id="test-editormd-view">
    //             <!-- <textarea style="display:none;" name="test-editormd-markdown-doc">###Hello world!</textarea> -->
    //         </div>
    //     </div>
    //     <script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/examples/js/jquery.min.js"></script>
    //     <script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/marked.min.js"></script>
    //     <script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/prettify.min.js"></script>
    //     <script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/raphael.min.js"></script>
    //     <script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/underscore.min.js"></script>
    //     <script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/sequence-diagram.min.js"></script>
    //     <script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/flowchart.min.js"></script>
    //     <script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/lib/jquery.flowchart.min.js"></script>
    //     <script src="//cdn.jsdelivr.net/gh/pandao/[email protected]/editormd.js"></script>
    //     <script type="text/javascript">
    //         $(function () {
    //             var testEditormdView = editormd.markdownToHTML("test-editormd-view", {
    //                 markdown: unescape('${escape(markdown)}'),
    //                 //htmlDecode      : true,       // 开启 HTML 标签解析,为了安全性,默认不开启
    //                 htmlDecode: "style,script,iframe", // you can filter tags decode
    //                 //toc             : false,
    //                 tocm: true, // Using [TOCM]
    //                 //tocContainer    : "#custom-toc-container", // 自定义 ToC 容器层
    //                 //gfm             : false,
    //                 //tocDropdown     : true,
    //                 // markdownSourceCode : true, // 是否保留 Markdown 源码,即是否删除保存源码的 Textarea 标签
    //                 emoji: true,
    //                 taskList: true,
    //                 tex: true, // 默认不解析
    //                 flowChart: true, // 默认不解析
    //                 sequenceDiagram: true, // 默认不解析
    //             });
    //         });
    //     </script>
    // </body>

    // </html>
    //   `

}
  • favicon.ico
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var url = new URL(request.url);

switch (url.pathname.replace(/^\/+/, "").toLowerCase()) {
  
    case "":
    case "help".toLowerCase():
    case "README_zh-cn.md".toLowerCase(): {
      return new Response(savefrom.Help(url), {
        status: 200,
        headers: {
          "Content-Type": "text/html; charset=UTF-8",
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Methods': '*',
        }
      });
    }

    case "favicon.ico".toLowerCase(): {
      return fetch("https://cloudflare.com/favicon.ico");
    }

}
  • DoProxy
1
2
3
4
5
6
7
8
9
10
11
12
export async function DoProxy(request: Request, url: string): Promise<Response> {

  return fetch(url,
    {
      method: request.method,
      body: request.body,
      headers: request.headers,
      keepalive: request.keepalive,
    }
  );

}