具有https支持的Node.js代理服务器

时间:2014-03-24 20:20:04

标签: windows node.js https proxy

我正在尝试编写将代理(几乎)所有http / s请求的代理服务器。几乎所有因为我需要捕获某些特定https网址的请求,并且响应从hdd发送文件而不是来自网络的真实响应。

整个解决方案应该在浏览器中充当代理,并且必须在Windows 7上工作。我从基于express.js的我自己的代理开始。它工作得很好......但不幸的是没有通过https。然后我试图使用几个来自github(https://github.com/horaci/node-mitm-proxyhttps://github.com/Hypermediaisobar/hyperProxy和其他少数几个的现有node.js代理服务器,但其中任何一个都在https上的windows环境中工作(或者我不知道如何他们)。

最后,我发现互联网代码中的某个地方(没有源代码链接)通过https工作(参见下面的代码)。这段代码的问题是,我找不到正确的方法来检查传入的请求URL,并根据请求url以不同的方式处理它们。  如果有人可以帮助我,我将不胜感激。

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

var debugging = 0;

var regex_hostport = /^([^:]+)(:([0-9]+))?$/;

function getHostPortFromString(hostString, defaultPort) {
  var host = hostString;
  var port = defaultPort;

  var result = regex_hostport.exec(hostString);
  if (result != null) {
    host = result[1];
    if (result[2] != null) {
      port = result[3];
    }
  }

  return( [ host, port ] );
}

// handle a HTTP proxy request
function httpUserRequest(userRequest, userResponse) {
  var httpVersion = userRequest['httpVersion'];
  var hostport = getHostPortFromString(userRequest.headers['host'], 80);

  // have to extract the path from the requested URL
  var path = userRequest.url;
  result = /^[a-zA-Z]+:\/\/[^\/]+(\/.*)?$/.exec(userRequest.url);
  if (result) {
    if (result[1].length > 0) {
      path = result[1];
    } else {
      path = "/";
    }
  }

  var options = {
    'host': hostport[0],
    'port': hostport[1],
    'method': userRequest.method,
    'path': path,
    'agent': userRequest.agent,
    'auth': userRequest.auth,
    'headers': userRequest.headers
  };

  var proxyRequest = http.request(
    options,
    function (proxyResponse) {
      userResponse.writeHead(proxyResponse.statusCode, proxyResponse.headers);

      proxyResponse.on('data', function (chunk) {
          userResponse.write(chunk);
        }
      );

      proxyResponse.on('end',
        function () {
          userResponse.end();
        }
      );
    }
  );

  proxyRequest.on('error', function (error) {
      userResponse.writeHead(500);
      userResponse.write(
        "<h1>500 Error</h1>\r\n<p>Error was <pre>" + error + "</pre></p>\r\n</body></html>\r\n";
      );
      userResponse.end();
    }
  );

  userRequest.addListener('data', function (chunk) {
      proxyRequest.write(chunk);
    }
  );

  userRequest.addListener('end', function () {
      proxyRequest.end();
    }
  );
}

    function main() {
      var port = 5555; // default port if none on command line

      // check for any command line arguments
      for (var argn = 2; argn < process.argv.length; argn++) {
        if (process.argv[argn] === '-p') {
          port = parseInt(process.argv[argn + 1]);
          argn++;
          continue;
        }

        if (process.argv[argn] === '-d') {
          debugging = 1;
          continue;
        }
      }

      if (debugging) {
        console.log('server listening on port ' + port);
      }

      // start HTTP server with custom request handler callback function
      var server = http.createServer(httpUserRequest).listen(port);

      server.addListener('checkContinue', function (request, response){
        console.log(request);
        response.writeContinue();
      });
      // add handler for HTTPS (which issues a CONNECT to the proxy)
      server.addListener(
        'connect',
        function (request, socketRequest, bodyhead) {
          var url = request['url'];
          var httpVersion = request['httpVersion'];
          var hostport = getHostPortFromString(url, 443);

          // set up TCP connection
          var proxySocket = new net.Socket();

          proxySocket.connect(
            parseInt(hostport[1]), hostport[0],
            function () {

                  console.log("ProxySocket: " + hostport[1] + " | " + hostport[0]);
                  proxySocket.write(bodyhead);

              // tell the caller the connection was successfully established
              socketRequest.write("HTTP/" + httpVersion + " 200 Connection established\r\n\r\n");
            }
          );

          proxySocket.on('data', function (chunk) {
              socketRequest.write(chunk);
            }
          );

          proxySocket.on('end', function () {
              socketRequest.end();
            }
          );

          socketRequest.on('data', function (chunk) {
              proxySocket.write(chunk);
            }
          );

          socketRequest.on('end', function () {
              proxySocket.end();
            }
          );

          proxySocket.on('error', function (err) {
              socketRequest.write("HTTP/" + httpVersion + " 500 Connection error\r\n\r\n");
              socketRequest.end();
            }
          );

          socketRequest.on('error', function (err) {
              proxySocket.end();
        }
          );
        }
      ); // HTTPS connect listener
    }

    main();

2 个答案:

答案 0 :(得分:0)

你要的是

吗?

http://expressjs.com/4x/api.html#req.secure req.secure - &gt; HTTPS

http://expressjs.com/4x/api.html#req.protocol req.protocol - &gt; HTTP

http://expressjs.com/4x/api.html#req.host req.host

req.url

这应该都在你的userRequest上

我可能没有正确理解你的问题。

答案 1 :(得分:0)

只需添加以下行:   var https = require('https'); 当您定期发出http请求时,请使用http.request,对于ssl请求,请使用https.request。