当前位置: 首页> 房产> 建筑 > 浅析Node.js中http代理的实现

浅析Node.js中http代理的实现

时间:2025/7/15 5:32:24来源:https://blog.csdn.net/jiangnanjunxiu/article/details/139801677 浏览次数:0次

文章目录

    • 前言
    • `ReadableStream`和`WritableStream`
    • `req.pipe`
    • 小结

前言

起因是狼书卷1中的API Proxy例子,代码如下:

const http = require('http')
const fs = require('fs')const app = http.createServer((req, res) => {if ('/remote' === req.url) {res.writeHead(200, { 'Content-Type': 'text/plain' })return res.end('Hello remote page!\n')} else {proxy(req, res)}
})function proxy(req, res) {const options = {host: req.host,port: 3000,path: 'remote',method: req.method, //原文是GETheaders: req.headers,agent: false}let httpProxy = http.request(options, (response) => {response.pipe(res)})req.pipe(httpProxy)
}app.listen(3000, function () {const PORT = app.address().portconsole.log(`Server running at http://127.0.0.1:${PORT}/}`)
})

例子没有什么问题,很好的实现了一个简单的http代理. 但读代码的过程中,还是发现了一些可以略做深究的点,记录如下。

ReadableStreamWritableStream

我们从代码说起,这个proxy的核心方法是:

function proxy(req, res) {const options = {host: req.host,port: 3000,path: 'remote',method: req.method, //原文是GETheaders: req.headers,agent: false}let httpProxy = http.request(options, (response) => {response.pipe(res)})req.pipe(httpProxy)
}

这个方法中,创建了转发请求需要的options, 其中包含目标服务器的信息,请求地址,以及请求头headers.
proxy方法的两个参数分别是req,res. req是一个Readable Streamres是一个Writable Stream. 这里要注意,readable还是writable是在server的角度来看的:server需要从req中读取请求信息,把返回的内容写入到res中.

在整个代理的过程中,依靠的是pipe来连接,pipe实现的功能是连接Readable StreamWritable Stream,反之亦然.
reqres的读写属性我们刚才分析了,现在来看httpProxy和方法回调中的response,但是这时,要从client角度来看了,response是远程服务返回的信息,是一个ReadableStream. httpProxyhttp.request返回的值,类型是http.ClientRequest, 继承自OutgoingMessage,也是一个Writable stream.

我们整理一下

ObjectRead/Write
reqReadable
resWritable
httpProxyWritable
responseReadable

到这里,流程非常清楚了

req(readable) ⇒ httpProxy(writable)
response(readable) ⇒ res(writable)

整个代理的流程厘清了.

req.pipe

读代码的时候,还想到了一个问题, httpProxy = http.request 这一行,不是已经发起请求吗, 为什么最后还要req.pipe?

这里涉及到http.request的请求过程,在调用这个方法的时候,实际上只是发出了请求头,此时并不能认为这个请求已经完成,例如POST请求就可能会要写入其它的数据到stream中。所以,这里req.pipe是将原始请求的流定向到了代理请求中,确保所有数据都写入。

用一个简单的例子就能看清楚

const http = require('http');// POST 请求选项
const options = {hostname: 'www.example.com',port: 80,path: '/submit-form',method: 'POST',headers: {'Content-Type': 'application/x-www-form-urlencoded'}
};// 发送POST请求
const req = http.request(options, (res) => {let data = '';res.on('data', (chunk) => {data += chunk;});res.on('end', () => {console.log(data);});
});// 发送请求数据
req.write('key1=value1&key2=value2');
req.end();

例子中,req 就要通过write 进行请求数据的写入.

所以req.pipe 是必须的,因为需要保证请求的stream中所有数据被转发.

小结

本文简单分析了Node.js实现proxy的一些容易忽略的知识点,涉及可读可写流,以及http请求的发起过程. 欢迎交流。

关键字:浅析Node.js中http代理的实现

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: