web-dev-qa-db-ja.com

httpサーバーをhttpリクエストにパイプすることによる単純なnode.jsプロキシ

単純なhttpプロキシサーバーを作成して、node.jsの詳細を学ぼう。使用シナリオは簡単です:ユーザー->プロキシ->サーバー->プロキシ->ユーザー

次のコードは、最後のステップまで機能します。コネクタの出力をユーザーにパイプで戻す方法が見つかりませんでした。

#!/usr/bin/env node

var
    url = require('url'),
    http = require('http'),
    acceptor = http.createServer().listen(3128);

acceptor.on('request', function(request, response) {
    console.log('request ' + request.url);
    request.pause();
    var options = url.parse(request.url);
    options.headers = request.headers;
    options.method = request.method;
    options.agent = false;

    var connector = http.request(options);
    request.pipe(connector);
    request.resume();
//  connector.pipe(response); // doesn't work
//  connector.pipe(request); // doesn't work either
});

Tcpflowを使用すると、ブラウザーからの着信要求、次に発信プロキシー要求、そしてプロキシーへのサーバー応答が表示されます。どういうわけか、ブラウザに応答を再送信することができませんでした。

このロジックをパイプで実装する適切な方法は何ですか?

15

「一時停止」する必要はありません。「パイプ」だけでOKです

var connector = http.request(options, function(res) {
  res.pipe(response, {end:true});//tell 'response' end=true
});
request.pipe(connector, {end:true});

「終了」であると伝えるまで、HTTPリクエストは終了しません。

24
Jay

OK。とった。

更新:NB!コメントで報告されているように、この例はもう機能しません。おそらくStreams2 APIの変更(ノード0.9以降)が原因です。

クライアントへのパイピングは、次のようにコネクタのコールバック内で発生する必要があります。

#!/usr/bin/env node

var
    url = require('url'),
    http = require('http'),
    acceptor = http.createServer().listen(3128);

acceptor.on('request', function(request, response) {
    console.log('request ' + request.url);
    request.pause();
    var options = url.parse(request.url);
    options.headers = request.headers;
    options.method = request.method;
    options.agent = false;

    var connector = http.request(options, function(serverResponse) {
            serverResponse.pause();
            response.writeHeader(serverResponse.statusCode, serverResponse.headers);
            serverResponse.pipe(response);
            serverResponse.resume();
    });
    request.pipe(connector);
    request.resume();
});
22

この投稿の例を使用して、http/sリクエストをプロキシしました。クッキーがどこかで失われるという問題に直面しました。

したがって、これを修正するには、プロキシ応答からのヘッダーを処理する必要があります。

作業例の下:

req = service.request(options, function(res) {
    response.writeHead(res.statusCode, res.headers);
    return res.pipe(response, {end: true});
});
request.pipe(req, {end: true});
3
kashesandr