【问题标题】:Node.js proxy, dealing with gzip DEcompressionNode.js代理,处理gzip解压
【发布时间】:2011-01-04 14:27:13
【问题描述】:

我目前正在使用代理服务器,在这种情况下,我们必须修改通过它推送的数据(通过使用正则表达式)。

在大多数情况下它工作正常,除了使用 gzip 作为内容编码的网站(我认为),我遇到了一个名为 compress 的模块,并试图通过解压缩 / gunzip 流推送我收到的块但结果并没有像我预期的那样。 (代码见下文)

我想我会发布一些代码来支持我的问题,这是加载了 mvc (express) 的代理:

module.exports = {
index: function(request, response){
    var iframe_url = "www.nu.nl"; // site with gzip encoding    

    var http = require('http');     
    var httpClient = http.createClient(80, iframe_url);
    var headers = request.headers;
    headers.host = iframe_url;

    var remoteRequest = httpClient.request(request.method, request.url, headers);

    request.on('data', function(chunk) {
        remoteRequest.write(chunk);
    });

    request.on('end', function() {
        remoteRequest.end();
    });

    remoteRequest.on('response', function (remoteResponse){         
        var body_regexp = new RegExp("<head>"); // regex to find first head tag
        var href_regexp = new RegExp('\<a href="(.*)"', 'g'); // regex to find hrefs

        response.writeHead(remoteResponse.statusCode, remoteResponse.headers);

        remoteResponse.on('data', function (chunk) {
    var body = doDecompress(new compress.GunzipStream(), chunk);
            body = body.replace(body_regexp, "<head><base href=\"http://"+ iframe_url +"/\">");
            body = body.replace(href_regexp, '<a href="#" onclick="javascript:return false;"');             

            response.write(body, 'binary');
        });

        remoteResponse.on('end', function() {

            response.end();
            });
        });
    }
};

在 var 正文部分,我想读取正文,例如,在这种情况下,通过将所有 href 替换为 # 来删除它们。这里的问题当然是当我们有一个 gzip 编码/压缩的网站时,它都是乱码,我们不能应用正则表达式。

现在我已经厌倦了使用 node-compress 模块:

 doDecompress(new compress.GunzipStream(), chunk);

指的是

function doDecompress(decompressor, input) {
  var d1 = input.substr(0, 25);
  var d2 = input.substr(25);

  sys.puts('Making decompression requests...');
  var output = '';
  decompressor.setInputEncoding('binary');
  decompressor.setEncoding('utf8');
  decompressor.addListener('data', function(data) {
    output += data;
  }).addListener('error', function(err) {
    throw err;
  }).addListener('end', function() {
    sys.puts('Decompressed length: ' + output.length);
    sys.puts('Raw data: ' + output);
  });
  decompressor.write(d1);
  decompressor.write(d2);
  decompressor.close();
  sys.puts('Requests done.');
}

但它失败了,因为块输入是一个对象,所以我尝试将它作为一个 chunk.toString() 提供,它也因输入数据无效而失败。

我想知道我是否朝着正确的方向前进?

【问题讨论】:

    标签: proxy compression gzip node.js content-encoding


    【解决方案1】:

    解压器需要二进制编码的输入。您的响应收到的块是 Buffer 的一个实例,toString() 方法默认情况下会返回一个 UTF-8 编码的字符串。

    所以你必须使用chunk.toString('binary') 才能使其工作,这也可以在demo 中看到。

    【讨论】:

    • 感谢您的回复,但是当我将其更改为: var body = doDecompress(new compress.GunzipStream(), chunk.toString('binary'));它仍然在 doDecompress 函数的第 17 行抛出错误,并带有“输入数据损坏”
    • 您的输入是分块编码的吗?如果没有,那么您需要在解压缩之前缓冲整个主体。所以你需要把chunks.toString('binary')加在一起,并在end回调中调用解压器。
    • 谢谢,看来确实是这个问题,我不得不将它们添加到一个变量中,最后进行解压缩。看来我现在可以做我想做的了,非常感谢!
    • 我现在唯一遇到的问题是,当我将输出输出到控制台时,我确实得到了完整的 html,但由于某种原因,只有在将其写入响应时才显示一半的站点。在解压器​​的“结束”回调中执行 -> proxysponse.end(output);
    • node -v 返回 v0.2.5,实际上我的意思是浏览器中显示了网站的一半。*
    猜你喜欢
    • 2011-06-02
    • 1970-01-01
    • 2011-05-21
    • 2012-08-14
    • 2021-06-19
    • 2010-12-17
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多