Node.js прокси-сервер, занимающийся распаковкой gzip
-
15-10-2019 - |
Вопрос
В настоящее время я работаю над прокси-сервером, где мы в этом случае должны изменять данные (с помощью регулярного выражения), которые мы передаем через него.
В большинстве случаев это работает нормально, за исключением веб-сайтов, которые используют gzip в качестве кодировки контента (я думаю), я наткнулся на модуль под названием сжимать и попытался протолкнуть куски, которые я получаю, через поток распаковки / 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 я хочу прочитать тело и, например, в этом случае удалить все hrefs, заменив их на #.Проблема здесь, конечно, в том, что когда у нас есть сайт, который закодирован / сжат в gzip, все это чушь собачья, и мы не можем применить регулярные выражения.
теперь я уже устал возиться с модулем сжатия узлов:
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.');
}
Но это не удается, поскольку входной фрагмент является объектом, поэтому я попытался предоставить его как фрагмент.toString(), который также завершается с ошибкой из-за недопустимых входных данных.
Мне было интересно, двигаюсь ли я вообще в правильном направлении?
Решение
Декомпрессор ожидает ввода в двоичном кодировании.Фрагмент, который получает ваш ответ, является экземпляром Буфер который toString()
метод по умолчанию возвращает вам строку в кодировке UTF-8.
Поэтому вы должны использовать chunk.toString('binary')
чтобы это сработало, это также можно увидеть на ДЕМОНСТРАЦИЯ.