2014-03-24 272 views
2

我想寫代理服務器,將代理(幾乎)所有http/s請求。幾乎所有,因爲我需要一些特定的https url的catch請求,並作爲響應從hdd發送文件,而不是從web的真實迴應。Node.js代理服務器與https支持

整個解決方案應該在瀏覽器中作爲代理工作,並且必須在Windows 7上工作。我開始使用基於express.js的自己的代理。它工作得很好......但不幸的是不通過https。然後我試着用github中的幾個現有的node.js代理服務器(https://github.com/horaci/node-mitm-proxy,https://github.com/Hypermediaisobar/hyperProxy和其他幾個),但他們中的任何一個都在https環境下工作(或者我不知道如何控制它們)。

最後我在互聯網代碼(沒有鏈接到源代碼)找到某個地方,它通過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(); 
+0

相關和解決方案提供在http://stackoverflow.com/a/32104777/786389 – y3sh

回答

0

只需添加以下行: var https = require('https'); 而且當您定期發送http請求時,請使用http.request,以及ssl請求https.request。

相關問題