惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threat Research - Cisco Blogs
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
V
Vulnerabilities – Threatpost
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
S
Secure Thoughts
Microsoft Azure Blog
Microsoft Azure Blog
Blog — PlanetScale
Blog — PlanetScale
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Tailwind CSS Blog
S
SegmentFault 最新的问题
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
The Last Watchdog
The Last Watchdog
L
LINUX DO - 热门话题
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
AWS News Blog
AWS News Blog
美团技术团队
G
Google Developers Blog
宝玉的分享
宝玉的分享
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
Recent Commits to openclaw:main
Recent Commits to openclaw:main
I
InfoQ
小众软件
小众软件
Google DeepMind News
Google DeepMind News
P
Privacy & Cybersecurity Law Blog
Stack Overflow Blog
Stack Overflow Blog
Webroot Blog
Webroot Blog
D
DataBreaches.Net
IT之家
IT之家
PCI Perspectives
PCI Perspectives
人人都是产品经理
人人都是产品经理
Hacker News: Ask HN
Hacker News: Ask HN
L
LangChain Blog
SecWiki News
SecWiki News
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cisco Blogs
T
Threatpost
P
Proofpoint News Feed
Y
Y Combinator Blog
Cloudbric
Cloudbric
T
Tor Project blog
量子位
博客园_首页
B
Blog
Hugging Face - Blog
Hugging Face - Blog
GbyAI
GbyAI
D
Darknet – Hacking Tools, Hacker News & Cyber Security

Claude's Blog

浅谈 npm 依赖治理 如何管理桌面窗口 SSR 页面 CDN 缓存实践 从 is-promise 事件我们可以学到什么 分享一个 npm dist-tag 的冷知识 从 Vimium 到 qutebrowser Verdaccio 性能优化:单机 Cluster 让 npm install 不使用缓存的方法 Verdaccio 性能优化:代理分流 Verdaccio 性能优化:上游路径转发 CSAPP DataLab 题解 不靠谱的 Egg.js 框架开发指南 如何解决 Debian 系 Elastic apm-server 7.x 启动失败 Hexo NexT 主题升级 7.4 From Journeyman to Master Mac 上移除 EasyConnect 常驻后台进程 Nginx SWRR 算法解读 记一次 Node.js 进程挂起的 BUG 追踪 警惕 Travis CI 的 npm 缓存
记录 Got(Node.js) 代理 HTTP 请求的坑
Post author: Claude Ray · 2021-01-27 · via Claude's Blog

在过去,request 模块几乎是 Node.js 端的不二选择,可惜已被放弃维护。如今流行的模块虽然变多,但不意味着它们足够成熟,我还是倾向于专注 Node.js 端的那几个。

需求越简单,选择越不重要。不过相较而言,Got 的接口设计看起来更友好,并且它是做到支持 Connection Timeout 和 Read Timeout 的少数。

https://github.com/sindresorhus/got/#comparison 的 Advanced timeouts

实际用下来,还是遇到了坑,顺便扒了一眼 Got 的代码。

native http?

先解释一下为什么不用原生 http 模块吧。

毕竟在 Node.js 提供代理服务是非常容易的事儿,普遍的优化无非是:

  • 使用 http.Agent。用它来支持 keepAlive,关闭 Nagle 算法等等。
  • 使用 stream.pipe()。相对于“接收-等待-发送”的模式,一方面主要是节省内存,另一方面可以减少等待,提高传输效率(但也不是绝对的)。

不用安装第三方依赖,基于原生 http 写上十来行代码即可完工,所以我自己很喜欢直接用 http 做一些工作。

但如果代理需求变得复杂,使用现成的轮子才能利于队友们(也包括自己)维护。

decompress

Got 默认对响应执行 decompress,对于代理而言毫无意义,需要关掉。

1
2
3
4
5
6
7
async _onResponseBase(response: IncomingMessageWithTimings): Promise<void> {
const {options} = this;

if (options.decompress) {
response = decompressResponse(response);
}
}

这在 decompress 的文档上有说明,但是一点儿都不醒目。

If this is disabled, a compressed response is returned as a Buffer. This may be useful if you want to handle decompression yourself or stream the raw compressed data.

最坑的是,我是因为遇到了 stream 的 bug (#issues/1279) 才注意到这个选项。在开启 decompress 的情况下,使响应值的 content-length 是错误的,该 bug 会导致返回的结果不完整。

accept-encoding

关闭 decompress 之后,响应开始变慢到肉眼可见得慢。

原因如下:

1
2
3
4
5
6
7
8
async _makeRequest(): Promise<void> {
const {options} = this;
const {headers} = options;

if (options.decompress && is.undefined(headers['accept-encoding'])) {
headers['accept-encoding'] = supportsBrotli ? 'gzip, deflate, br' : 'gzip, deflate';
}
}

accept-encoding 只在 decompress 为 true 的时候设置,否则无法享用 gzip 等压缩带来的优化。

solution

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
const got = require('got');
const HttpAgent = require('agentkeepalive');
const HttpsAgent = HttpAgent.HttpsAgent;

const sec = 1000;
const min = 60 * sec;

const supportsBrotli = process.versions.brotli;

const request = got.extend({
agent: {
http: new HttpAgent(),
https: new HttpsAgent(),
},


decompress: false,

headers: {
'accept-encoding': supportsBrotli ? 'gzip, deflate, br' : 'gzip, deflate',
},
timeout: {
connect: 3 * sec,
socket: 2 * min,
},
});

这大概率不是最终版,立一个 flag,如果再遇到问题,就自己从头写一个专用于代理场景的 http 库。