0

アップストリームの http.IncomingMessage を、restify サーバー経由でクライアントに転送したいと考えています。これが私が今まで思いついたものです。転送機能を提供します。ただし、これによりメモリリークが発生する可能性があると思います。

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()
})
  • アップストリームの場合、このコードは決して消費されない (いいえ) ため、本体 (1) を404リークすると思いますか?upstreamRespipe(somewhere)
  • ボディをリークしてはならない明白な解決策 (2) の 1 つupstreamResは、 にパイプすること/dev/nullです。この問題の代替/より良い解決策はありますか?
4

1 に答える 1

0

に関するドキュメントの重要なセクションをスキップしたようですhttp.ClientRequest

「応答」ハンドラが追加されていない場合、応答は完全に破棄されます。ただし、「応答」イベント ハンドラーを追加する場合は、「読み取り可能な」イベントがあるたびに response.read() を呼び出すか、「データ」ハンドラーを追加して、応答オブジェクトからデータを消費する必要があります。 .resume() メソッドを呼び出します。データが消費されるまで、「終了」イベントは発生しません。また、データが読み取られるまでメモリが消費され、最終的に「プロセスがメモリ不足」エラーにつながる可能性があります。

https://nodejs.org/api/http.html#http_class_http_clientrequest

したがって、正しい答えは次のようです。

  • http.IncomingMessageそれぞれのレスポンス(a)を消費する必要がありますhttp.ClientRequest
  • 返されたデータに関心がない場合は、 を呼び出すことをお勧めしますupstreamRes.resume()。これにより、コンシューマがアタッチされていなくてもデータ フローが開始されます。
于 2016-06-08T11:03:26.430 に答える