Innos Note as Blog

date
Oct 24, 2021
slug
innos-note-as-blog
status
Published
tags
Archive - Innos
summary
type
Post
难得的周六,研究了一下这个叫 Frution 的项目(用 Notion 搭建网站):
结果发现就是个反代。我之前还以为 SPA 的反代应该挺麻烦的,万一要是把域名硬编码进了代码就麻烦。但是既然 Notion 都可以被反代了,那我的这个 Innos Note 是不是也可以用 Cloudflare Workers 反代一下?
于是鼓捣了一天后,得到了这个:
基本上“只读”的功能经过反代后都是正常的,唯一不好解决的就是登录,但我也没想支持登录功能,毕竟要用到登录的话不如乖乖打开 Innos Note。于是我还挺想把登录按钮给隐藏掉的,但是发现不太好隐藏,类名看起来是在编译的时候随机生成的(有 CSS in JS 的味道了),万一他们发个新版本就把类名改掉了🤣
notion image
目前也能正常支持 Telegram 的网页预览,如果想让预览更丰富的话应该也是可以的,毕竟 meta 可以随便更改,页面内容也会被 SSR 渲染出来。
做这个小轮子的时候有一个有意思的事情是,直接反代过后发生了许多脚本请求错误,看了一下大多都是前端打点监控相关的,于是想着不如干掉这些监控。但是要干掉这些监控的话,靠正则去匹配 script 标签感觉还挺麻烦的,似乎更好的办法是解析整个 HTML,然后用类似 DOM API 提供的方法去操作这个文档,最后把操作完的文档再序列化成 HTML 传给用户。
我隐隐约约觉得这里可能会有性能问题,于是查了下我之前用过的一个叫 cheerio 的库的性能,看起来似乎还是挺好的,宣称8倍于 jsdom。于是我就用上了,为此我还从 Cloudflare Workers 管理页面上的 Quick Edit 转成在 GitHub Codespaces 上使用 Wrangler,不然还没法引用 npm 包。
简单调试几遍后发现效果还可以,于是俺就 wrangler publish 了。结果我刷新了几次 workers.dev 后,Cloudflare 直接给我返回 Resource limit exceeded。卧槽,该不会我今天的十万请求数给用光了吧,然后打开后台一看:
notion image
CPU 时间直接好几百(Cloudflare Workers 免费版的限制是 10ms),这显然是不正常的。于是第一个怀疑的对象就是 HTML 解析与处理的这个环节,我就试着把我刚才加上的代码去掉,马上就变成只有几毫秒了。
但是网页处理还是必要的,有没有什么办法降低延迟呢?噢,听说 Cloudflare 支持 wasm,那我是不是可以用一些别的语言,比如 Rust,来做这个网页的处理呢?
可惜俺不会 Rust,但是为了实现这个我觉得还是可以试着学一学的,正好一直都想学一下 Rust。后来就是看到 Rust by Example 的 1.2.2 节我就没再看下去了,语法看得让人想睡觉,看来我现在连学一门新语言的能力也逐渐丧失了(
Cloudflare 官方是有提供 Rust Workers 样例的,只是我看不懂怎么在 Rust 里调用 Fetch API。正当我想找找有没有其他教程的时候:
notion image
页面上倒数第二个教程叫 Localize a website with HTMLRewriter。嗯,这名字好像有点...?
点开一看,我天,这 HTMLRewriter 就是专门用来改写 HTML 的,而且也不是什么第三方库,是 Workers 的 Runtime API 之一,甚至还专门设计成了流式处理。。。(这时就很懊悔为什么没有早一些发现这个东西
不过因为是流式处理,整个 API 设计得就跟语法分析器一样hhh,所以也不能套用 DOM API / jQuery 的处理思路了。有一些需要注意的地方是:
  1. Element 和 Text 也是分开处理的,当读到新的 Element 时是无法获取它包含的 TextNode 的。此外,一旦 Element 被你的 handler “处理”完成后(也就是 return 之后),你也无法再次对 Element 进行处理(就算你在别的地方保存了 Element 的引用)。所以就不用想着根据 Text 来决定是否移除 Element 了,洗洗睡吧。
  1. TextNode 还可能被分成多次被读入,所以如果你想替换 TextNode 的文本,你最好自己维护一个 buffer 来记录当前 TextNode 的所有 Text,就像这个帖子里写的那样:
还有一个事情也花了好长时间,就是一开始的时候一堆接口死活请求不出来,F12 红大一片。最后才发现,Innos Note 的一些接口是需要登录态的(比如图片下载),登录态是在第一次访问页面时设置在一个叫 session 的 Cookie 里,于是 Workers 需要支持转发 Set-Cookie 响应头和 Cookie 请求头。However,这个 session Cookie 设置了 domain=.innos.io ,所以你直接转发也是没有用的,还需要去掉这个域名限制。
结果不知不觉一天就这么过去了,除了点麦当劳外卖的时间之外一直都在调 Cloudflare Workers,调着调着就到了第二天凌晨两点,澡也还没洗,天气又挺冷的,怕是今晚又是直接一个倒头就睡。
庆幸的是自己还是能够一口气写完一个东西的,就算这个东西说来挺小的,也算是满足了自己的一个需求。
未来也可以结合 Innos 的 OpenAPI 来做一些别的功能,不过现在这个 API 看起来质量还很差,API 文档跟实际的接口根本对不上。周六的时候在官方的 Discord 服务器里提问,过了一天之后杳无音信,字节新加坡果然是真正的双休工作制。
notion image

© Robin Wong 2012 - 2024