web-dev-qa-db-ja.com

node.jsで簡単なhttpプロキシを作成する方法は?

HTTP GETリクエストをクライアントからサードパーティのWebサイト(たとえばgoogle)に渡すプロキシサーバーを作成しようとしています。私のプロキシは、着信要求をターゲットサイト上の対応するパスにミラーリングするだけでよいため、クライアントの要求されたURLが次の場合は、

127.0.0.1/images/srpr/logo11w.png

次のリソースを提供する必要があります。

http://www.google.com/images/srpr/logo11w.png

ここに私が思いついたものがあります:

http.createServer(onRequest).listen(80);

function onRequest (client_req, client_res) {
    client_req.addListener("end", function() {
        var options = {
            hostname: 'www.google.com',
            port: 80,
            path: client_req.url,
            method: client_req.method
            headers: client_req.headers
        };
        var req=http.request(options, function(res) {
            var body;
            res.on('data', function (chunk) {
                body += chunk;
            });
            res.on('end', function () {
                 client_res.writeHead(res.statusCode, res.headers);
                 client_res.end(body);
            });
        });
        req.end();
    });
}

htmlページではうまく機能しますが、他の種類のファイルの場合は、ターゲットサイト(サイトによって異なります)から空白ページまたはエラーメッセージを返すだけです。

59

サードパーティのサーバーから受け取った応答を処理するのは良い考えだとは思いません。これにより、プロキシサーバーのメモリフットプリントが増加するだけです。さらに、それがコードが機能しない理由です。

代わりに、応答をクライアントに渡してみてください。次のスニペットを検討してください。

var http = require('http');

http.createServer(onRequest).listen(3000);

function onRequest(client_req, client_res) {
  console.log('serve: ' + client_req.url);

  var options = {
    hostname: 'www.google.com',
    port: 80,
    path: client_req.url,
    method: client_req.method,
    headers: client_req.headers
  };

  var proxy = http.request(options, function (res) {
    client_res.writeHead(res.statusCode, res.headers)
    res.pipe(client_res, {
      end: true
    });
  });

  client_req.pipe(proxy, {
    end: true
  });
}
78
vmx

以下は、nodejitsuの node-http-proxy を使用した実装です。

var http = require('http');
var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});

http.createServer(function(req, res) {
    proxy.web(req, res, { target: 'http://www.google.com' });
}).listen(3000);
21
bosgood

以下に、リダイレクトを処理する request を使用するプロキシサーバーを示します。プロキシURLを使用して使用します http://domain.com:3000/?url= [your_url]

var http = require('http');
var url = require('url');
var request = require('request');

http.createServer(onRequest).listen(3000);

function onRequest(req, res) {

    var queryData = url.parse(req.url, true).query;
    if (queryData.url) {
        request({
            url: queryData.url
        }).on('error', function(e) {
            res.end(e);
        }).pipe(res);
    }
    else {
        res.end("no url found");
    }
}
10
Henry

バイナリファイルはデータイベントハンドラーで文字列にキャストできないため、コードは機能しません。バイナリファイルを操作する必要がある場合は、 buffer を使用する必要があります。申し訳ありませんが、私の場合はHTMLファイルを操作する必要があるため、バッファの使用例はありません。コンテンツタイプを確認してから、必要に応じてtext/htmlファイルを更新します。

app.get('/*', function(clientRequest, clientResponse) {
  var options = { 
    hostname: 'google.com',
    port: 80, 
    path: clientRequest.url,
    method: 'GET'
  };  

  var googleRequest = http.request(options, function(googleResponse) { 
    var body = ''; 

    if (String(googleResponse.headers['content-type']).indexOf('text/html') !== -1) {
      googleResponse.on('data', function(chunk) {
        body += chunk;
      }); 

      googleResponse.on('end', function() {
        // Make changes to HTML files when they're done being read.
        body = body.replace(/google.com/gi, Host + ':' + port);
        body = body.replace(
          /<\/body>/, 
          '<script src="http://localhost:3000/new-script.js" type="text/javascript"></script></body>'
        );

        clientResponse.writeHead(googleResponse.statusCode, googleResponse.headers);
        clientResponse.end(body);
      }); 
    }   
    else {
      googleResponse.pipe(clientResponse, {
        end: true
      }); 
    }   
  }); 

  googleRequest.end();
});    
4
Mike Dilorenzo

非常にシンプルで読みやすいので、Node.jsだけを使用してローカルプロキシサーバーをローカルHTTPサーバーに作成します(v8.1.0でテスト済み)。統合テストに特に役立つことがわかったので、ここに私の共有を示します。

/**
 * Once this is running open your browser and hit http://localhost
 * You'll see that the request hits the proxy and you get the HTML back
 */

'use strict';

const net = require('net');
const http = require('http');

const PROXY_PORT = 80;
const HTTP_SERVER_PORT = 8080;

let proxy = net.createServer(socket => {
    socket.on('data', message => {
        console.log('---PROXY- got message', message.toString());

        let serviceSocket = new net.Socket();

        serviceSocket.connect(HTTP_SERVER_PORT, 'localhost', () => {
            console.log('---PROXY- Sending message to server');
            serviceSocket.write(message);
        });

        serviceSocket.on('data', data => {
            console.log('---PROXY- Receiving message from server', data.toString();
            socket.write(data);
        });
    });
});

let httpServer = http.createServer((req, res) => {
    switch (req.url) {
        case '/':
            res.writeHead(200, {'Content-Type': 'text/html'});
            res.end('<html><body><p>Ciao!</p></body></html>');
            break;
        default:
            res.writeHead(404, {'Content-Type': 'text/plain'});
            res.end('404 Not Found');
    }
});

proxy.listen(PROXY_PORT);
httpServer.listen(HTTP_SERVER_PORT);

https://Gist.github.com/fracasula/d15ae925835c636a5672311ef584b999

2

私は、メッセージをオプションでデコードしてHTTPSを処理するプロキシをnodejsで作成しました。このプロキシは、企業プロキシを経由するためにproxy-authentificationヘッダーを追加することもできます。企業プロキシの使用を設定するには、引数としてproxy.pacファイルを見つけるためのURLを指定する必要があります。

https://github.com/luckyrantanplan/proxy-to-proxy-https

0