【问题标题】:How to listen to node http-proxy traffic?如何监听节点 http-proxy 流量?
【发布时间】:2012-03-16 17:12:03
【问题描述】:

我正在使用node-http-proxy。但是,除了中继 HTTP 请求之外,我还需要监听传入和传出的数据。

拦截响应数据是我苦苦挣扎的地方。 Node 的 ServerResponse 对象(以及更一般的 WritableStream 接口)不会广播 'data' 事件。 http-proxy 似乎创建了它自己的内部请求,它产生了一个 ClientResponse 对象(它确实广播了 'data' 事件)但是这个对象并没有在代理之外公开暴露。

有什么想法可以在不使用猴子补丁 node-http-proxy 或在响应对象周围创建包装器的情况下解决这个问题吗?

【问题讨论】:

    标签: http node.js proxy


    【解决方案1】:

    Github 上 node-http-proxy 问题中的相关问题似乎暗示这是不可能的。对于其他人未来的尝试,这是我破解问题的方式:

    • 您会很快发现代理只调用了res 对象的writeHead()write()end() 方法
    • 由于res 已经是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)
    

    【讨论】:

    • 这太好了,谢谢!但是,在将标头发送回客户端之前,我需要实际重写标头。您的示例只是收听/记录数据,但不会更改它。在将其发送回客户之前如何实际更改它的任何想法?
    • @Tauren - 如果你需要发送修改后的数据,你真的需要 3 件事:1. 读取传入的数据,2. 修改它,3. 继续发送。 node-http-proxy 的全部意义在于封装代理过程-在您的情况下,它对您的帮助并不大。所以我建议使用 node 的内置 HTTP 服务器和 mikeal 的优秀 request library 作为 HTTP 客户端来修补你的代理。
    • 感谢您的反馈。这与我得出的结论相同,但希望可能有某种方法来完成它并且仍然使用 node-http-proxy。它解决了我 99% 的需求,但有一个问题给我带来了麻烦。
    【解决方案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);
    

    【讨论】:

    • 我怎样才能让这段代码工作?我将浏览器配置为使用端口 5556,但导航到不同网站时控制台中没有显示任何内容...
    【解决方案3】:

    我尝试了您的 hack,但它对我不起作用。我的用例很简单:我想将来自 Android 应用的传入和传出流量记录到由基本身份验证保护的登台服务器。

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

    是我的解决方案。我的 node-http-proxy 总是返回 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()
    

    注意,这会打印任何二进制内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-26
      • 2017-10-24
      • 1970-01-01
      • 1970-01-01
      • 2011-08-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多