【Node.JS进阶学习计划】通过分析UnblockNeteaseMusic项目了解如何构建一个HTTP代理(一)

写在前面

最近学校停课了,课余时间一下就多了起来,但是虽然如此,还是鸽了许多作业(要赶紧补回来了)

话虽然是这么说,心里还是挺想折腾的。

前几天,安东尼给我看了个挺有意思的项目,ovebai/UnblockNeteaseMusic。他把这个项目部署在自己家里了,打算给群里的群友们用,但是测试下来发现运行不是很稳定,问我有没有啥能让他崩溃重启的方法,我建议他去使用pm2做进程守护,不过最后还是不了了之了。

后来我又粗略看了下这个项目,发现涉及了一些代理相关的内容,又看了下packages.json。我有点惊讶,这个项目居然一个第三方库都没使用,所以就来兴趣了,想通过分析这个项目,来学习下如何在不使用第三方库的情况下构建一个HTTP代理。

免责声明

本文仅在技术层面对该项目进行分析,不分享任何的代理信息,不以此作任何盈利。

开始分析

分析一个项目,第一件事肯定是阅读它的README信息。

从README中我们可以得知,这个项目是以cli的形式运行的,执行命令是

unblockneteasemusic

了解这些信息后,我们可以开始看 package.json 了。

从 package.json 中我们可以得知,unblockneteasemusic命令对应的入口文件是 app.js。

所以我们基本可以锁定,整个分析将要从 app.js 文件开始。

app.js 里首先引入了 package.json,目的是用来获取软件名和版本号等信息。

紧接着就是引入了 cli.js ,通过对文件名,我们可以猜测到整个 cli.js 是用于负责处理 cli 指令的,但至于具体如何处理的,还有待慢慢读源码才能知道。

这里我们可以看到在引入 cli.js 之后的数行里,作者使用链式调用的语法糖分别调用了 program, option, parse 三个方法。

通过观察调入的参数,我们大概可以猜测到

  • program方法是用来定义该软件的名称和当前版本号
  • option方法用来定义cli的各种命令,第一个参数是制定该命令的flags,接受的是数组;第二个参数是额外信息,接受的是一个对象。从实际调用我们可以得知,对象包含 metavar, nargs, help。
  • parse方法用于加载最终需要被解析的cli参数,这里通过Node.JS的process.argv获取

最终 cli 执行完后,主城获取到的是一个 config 对象。

打开 cli.js 后,发现果然不出所料,作者是通过在执行每个方法后返回 cli 自身,来实现了链式调用。

我打算先把 app.js 这个入口文件看完,所以就先不看 cli 模块了。

app.js 继续往下看,我们可以看到作者把cli传入的address放入了全局变量里,然后接着是对其他传入参数的校验。

接着作者引入了 url 模块的 parse 函数和项目下的 hook.js、 server.js 。

随后,作者把完成校验的配置都一并放入了全局变量 global 里。同时给在前面已经引入了的 server 加入了 whitelist 和 blacklist 两个数组,并且通过名字可以的猜测是用于设置代理的白名单和黑名单功能,是数组,但具体是如何使用的,则需要进一步阅读源码才能知晓。

并且在cli里设置的endpoint也会被放入whitelist数组中。

随后,作者引入 dns 库来解析host。

接着又引入项目下的 request.js 来实现 httpdns 的功能,并通过 Promise.all 来执行。

并且最后使用 reduce 和 concat 来连接数组

result.reduce((merged, array) => merged.concat(array), [])

并且使用 Array.from 和 Set 对象来去除重复对象

Array.from(new Set())

最后使用 server.http.listen 和 server.https.listen 来监听代理端口。

自此,该项目的入口文件已经阅读了一遍,我们发现项目大体上分为以下几个部分:

  • app.js – 项目入口文件
  • cli.js – 处理、格式化 cli 指令输入
  • hook.js – 暂时用途不明
  • server.js – 根据名字可以推测是处理服务流量
  • request.js – 抽象出来的请求模块

一些题外话

大概两年前,机缘巧合地,我了解到了水牛城大学,也了解了百度创始人李彦宏正是在那学成归国的,后来在知乎也从别的学长口中了解到,李彦宏的导师至今对李彦宏仍记忆深刻,称之为自己一个出色的弟子。

一切过得很快,但似乎都在情理之中,两年后的现在,我被这所大学录取,同时百度这家公司的吃相似乎也越来越难看。今天早上起床,看到PanDownload被抓的,我第一感觉也是觉得在情理之中。早在一年多前,我和一个朋友就讨论过这个问题,说从以前某个破解版QQ作者的下场来看,PanDownload的作者肯定会被百度制裁的,只不过不知道东窗事发的是哪一天而已。

当下,不仅是互联网行业,所有行业的巨头都有着无法触及的法务,而这些法务力量又成为这些垄断巨头的保护伞。如此一个时间,在如此庞然巨物看来,不痛不痒;但对于一个个人,一个开发者来说,这可能是10年时光,甚至更多。

我们开始去想,互联网的基础到底是什么,共享、开放?还是在商业巨头面前,仅仅是一个创造利润的机器。

如上一篇博文提到,我想做一个社区 tangen.cy ,在开始开发的初期,我就开始想资本对这个平台的影响。一旦某天我有幸把这个平台做大,我更希望的是保留社区用户的高质量,而不是一味为了利益的无下限地放纵用户在平台上上传无用内容。

我最近一直在想,成功的意义是什么,换句话说,我们穷极一生,在追求的到底是什么?是钱?名誉?地位?

我还没想好,但总感觉一切的一切,都得基于钱。

我问朋友,想不想去一次说走就走的旅行?他们最先答复的是,“啊,我最近钱不是很多,你想要去哪里?”

我才猛地反应过来,对啊,一切又绕回了那个最简单最淳朴的问题——你有多少钱?

我还没想通,但我相信,肯定有办法,或者说有一个平衡点,可以平衡金钱和理想。

参考资料

MDN:

分享到:

5 条评论

昵称

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

  1. Asttear

    提醒一下,被抓的是 PanDownload 的作者,而且这个软件是闭源的,与 GitHub 上的开源项目 PanDownloader 无关。后者也早就不能用了(虽然 PanDownload 也没好到哪儿去,但至少开会员后还能用它满速)。如果 PanDownload 开源的话也许麻烦事就少些了😔

    1. Y2Nk4

      对啊 感觉她接受捐赠的操作风险就非常大了

    2. Y2Nk4

      哈哈 才发现原文中写错了

  2. Ryoma

    钱确实是在如今社会框架下生活所不能回避的东西,而如何赚钱自然成为了身处社会中的人不得不思考的问题。但究其根本,钱和理想并不冲突,冲突的是社会给出的赚钱的方法和自己心中实现理想的方法。之前自己臆想过一个可能性:在能够实现理想的情况下脱离社会框架,还没等我臆想房东就给了我沉重的一击(该交房租了(´இ皿இ`)

    1. Y2Nk4

      对!冲突的是社会给出的赚钱的方法和自己心中实现理想的方法
      这句话真的无比认同了,分工和流水线化生产后产生的许多工种都挺乏味的。
      希望大共产主义可以早日来临(。•ˇ‸ˇ•。)