处理有条件的未消费 http.IncomingMessage
Handling of conditionally unconsumed http.IncomingMessage
我想通过 restify 服务器将上游 http.IncomingMessage 转发给客户端。这就是我到目前为止的想法。它提供转发能力。但是我认为这可能会导致内存泄漏:
var server = restify.createServer()
server.get('/test', function(req, res, next) {
var upstreamReq = createUpstreamReq() // just creates a http.ClientRequest
upstreamReq.on('response', function(upstreamRes) {
if (upstreamRes.statusCode === 404) {
// (1) I guess this leaks the upstreamRes body ?
return next(new restify.errors.NotFoundError())
}
if (upstreamRes.statusCode !== 200) {
// (2) is there a better way than pipeing the response to /dev/null?
// I guess the advantage of this approach is that we can reuse the connection (not closed) ?
upstreamRes.pipe(fs.createWriteStream('/dev/null'))
return next(new restify.errors.InternalServerError())
}
res.setHeader('Content-Type', upstreamRes.header('Content-Type'))
res.setHeader('Content-Length', upstreamRes.header('Content-Length'))
upstreamRes.pipe(res)
return next()
})
upstreamReq.end()
})
- 我假设在上游
404
的情况下,此代码会泄漏 upstreamRes
主体 (1),因为它从未被消耗(没有 pipe(somewhere)
)?
- 一个不应该泄漏
upstreamRes
主体的明显解决方案 (2) 是将其通过管道传输到 /dev/null
。这个问题有 alternative/better 解决方案吗?
我似乎跳过了文档中关于 http.ClientRequest
的一个重要部分:
If no 'response' handler is added, then the response will be entirely
discarded. However, if you add a 'response' event handler, then you
must consume the data from the response object, either by calling
response.read() whenever there is a 'readable' event, or by adding a
'data' handler, or by calling the .resume() method. Until the data is
consumed, the 'end' event will not fire. Also, until the data is read
it will consume memory that can eventually lead to a 'process out of
memory' error.
https://nodejs.org/api/http.html#http_class_http_clientrequest
所以正确答案似乎是:
- 您需要为每个
http.ClientRequest
使用响应(一个 http.IncomingMessage
)
- 如果您对返回的数据不感兴趣,建议的方法是调用
upstreamRes.resume()
。即使没有附加消费者,这也会启动数据流。
我想通过 restify 服务器将上游 http.IncomingMessage 转发给客户端。这就是我到目前为止的想法。它提供转发能力。但是我认为这可能会导致内存泄漏:
var server = restify.createServer()
server.get('/test', function(req, res, next) {
var upstreamReq = createUpstreamReq() // just creates a http.ClientRequest
upstreamReq.on('response', function(upstreamRes) {
if (upstreamRes.statusCode === 404) {
// (1) I guess this leaks the upstreamRes body ?
return next(new restify.errors.NotFoundError())
}
if (upstreamRes.statusCode !== 200) {
// (2) is there a better way than pipeing the response to /dev/null?
// I guess the advantage of this approach is that we can reuse the connection (not closed) ?
upstreamRes.pipe(fs.createWriteStream('/dev/null'))
return next(new restify.errors.InternalServerError())
}
res.setHeader('Content-Type', upstreamRes.header('Content-Type'))
res.setHeader('Content-Length', upstreamRes.header('Content-Length'))
upstreamRes.pipe(res)
return next()
})
upstreamReq.end()
})
- 我假设在上游
404
的情况下,此代码会泄漏upstreamRes
主体 (1),因为它从未被消耗(没有pipe(somewhere)
)? - 一个不应该泄漏
upstreamRes
主体的明显解决方案 (2) 是将其通过管道传输到/dev/null
。这个问题有 alternative/better 解决方案吗?
我似乎跳过了文档中关于 http.ClientRequest
的一个重要部分:
If no 'response' handler is added, then the response will be entirely discarded. However, if you add a 'response' event handler, then you must consume the data from the response object, either by calling response.read() whenever there is a 'readable' event, or by adding a 'data' handler, or by calling the .resume() method. Until the data is consumed, the 'end' event will not fire. Also, until the data is read it will consume memory that can eventually lead to a 'process out of memory' error.
https://nodejs.org/api/http.html#http_class_http_clientrequest
所以正确答案似乎是:
- 您需要为每个
http.ClientRequest
使用响应(一个 - 如果您对返回的数据不感兴趣,建议的方法是调用
upstreamRes.resume()
。即使没有附加消费者,这也会启动数据流。
http.IncomingMessage
)