2012-03-16 112 views
4

我正在使用node-http-proxy。但是,除了中繼HTTP請求之外,我還需要監聽傳入和傳出的數據。如何偵聽節點http-proxy流量?

攔截響應數據是我掙扎的地方。節點的ServerResponse對象(以及更一般的WritableStream接口)不會廣播'data'事件。 http-proxy似乎創建它自己的內部請求,它會產生一個ClientResponse對象(它不會廣播'data'事件),但是該對象不公開地在代理之外公開顯示。

任何想法如何解決這個沒有monkey-patching節點http-proxy或創建一個包裝的響應對象?

回答

5

在Github上node-http-proxy問題的相關問題似乎意味着這是不可能的。對於別人未來的嘗試,這裏是我如何破解問題:

  • 你很快就會發現,代理只調用res對象
  • 因爲reswriteHead()write()end()方法已經是EventEmitter,你就可以開始發射新的自定義事件
  • 偵聽這些新的事件來組裝響應數據,然後用它
var eventifyResponse = function(res) { 
    var methods = ['writeHead', 'write', 'end']; 
    methods.forEach(function(method){ 
    var oldMethod = res[method]; // remember original method 
    res[method] = function() { // replace with a wrapper 
     oldMethod.apply(this, arguments); // call original method 
     arguments = Array.prototype.slice.call(arguments, 0); 
     arguments.unshift("method_" + method); 
     this.emit.apply(this, arguments); // broadcast the event 
    }; 
    }); 
}; 

res = eventifyResponse(res), outputData = ''; 

res.on('method_writeHead', function(statusCode, headers) { saveHeaders(); }); 
res.on('method_write',  function(data) { outputData += data; }); 
res.on('method_end',  function(data) { use_data(outputData + data); }); 
proxy.proxyRequest(req, res, options) 
+0

這是偉大的,謝謝!但是,我需要在發送回客戶端之前實際重寫一個標頭。你的例子只是監聽/記錄數據,但不會改變它。有關如何在將其發送回客戶端之前實際進行更改的想法? – Tauren 2012-10-06 06:36:05

+0

@Tauren - 如果您需要發送修改後的數據,您確實需要3件事:1.讀取傳入數據,2.修改它,3.發送它。 'node-http-proxy'的全部內容是封裝代理進程 - 在你的情況下,它不會真的幫你很多。因此,我建議使用節點的內置HTTP服務器和mikeal的優秀[請求庫](https://github.com/mikeal/request)作爲HTTP客戶端將代理修補到一起。 – zzen 2012-10-06 10:44:03

+0

感謝您的反饋意見。這是我得出的結論,但希望可能有某種方法來實現它,並仍然使用node-http-proxy。它解決了我99%的需求,但有一個問題正在給我帶來麻煩。 – Tauren 2012-10-06 20:05:15

0

我試過你的黑客,但它沒有爲我工作。我的用例很簡單:我想將來自Android應用程序的輸入和輸出流量記錄到由基本身份驗證保護的暫存服務器。

https://github.com/greim/hoxy/

是我的解決方案。我的節點HTTP代理總是返回500(而直接請求階段沒有)。也許授權頭文件不會被正確地轉發或者其他。

Hoxy從一開始就工作得很好。

npm install hoxy [-g] 
hoxy --port=<local-port> --stage=<your stage host>:<port> 

至於日誌記錄規則指定我:

request: $aurl.log() 
request: @log-headers() 
request: $method.log() 
request: $request-body.log() 


response: $url.log() 
response: $status-code.log() 
response: $response-body.log() 

當心,這個打印任何二進制內容。

2

這是一個簡單的代理服務器監聽的流量並寫它安慰:

var http = require('http'), 
    httpProxy = require('http-proxy'); 

// 
// Create a proxy server with custom application logic 
// 
var proxy = httpProxy.createProxyServer({}); 

// assign events 
proxy.on('proxyRes', function (proxyRes, req, res) { 

    // collect response data 
    var proxyResData=''; 
    proxyRes.on('data', function (chunk) { 
     proxyResData +=chunk; 
    }); 
    proxyRes.on('end',function() { 


     var snifferData = 
     { 
      request:{ 
       data:req.body, 
       headers:req.headers, 
       url:req.url, 
       method:req.method}, 
      response:{ 
       data:proxyResData, 
       headers:proxyRes.headers, 
       statusCode:proxyRes.statusCode} 
     }; 
     console.log(snifferData); 
    }); 

    // console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2)); 
}); 


proxy.on('proxyReq', function(proxyReq, req, res, options) { 
    // collect request data 
    req.body=''; 
    req.on('data', function (chunk) { 
     req.body +=chunk; 
    }); 
    req.on('end', function() { 
    }); 

}); 

proxy.on('error', 
    function(err) 
    { 
     console.error(err); 
    }); 

// run the proxy server 
var server = http.createServer(function(req, res) { 

    // every time a request comes proxy it: 
    proxy.web(req, res, { 
     target: 'http://localhost:4444' 
    }); 

}); 

console.log("listening on port 5556") 
server.listen(5556); 
+0

如何獲得此代碼的工作?我將瀏覽器配置爲使用端口5556,但導航到不同網站時控臺上沒有任何內容顯示... – Valip 2017-05-10 10:52:14

相關問題