node.js - простые http-запросы со сжатием gzip/deflate
Я пытаюсь выяснить, как лучше всего отправлять запросы HTTP/HTTPS и обрабатывать сжатые ответы gzip/deflate вместе с файлами cookie.
Лучшее, что я нашел, было https://github.com/mikeal/request которое обрабатывает все, кроме сжатия. Есть ли модуль или метод, который будет делать все, что я спрашиваю?
Если нет, могу ли я каким-то образом объединить запрос и zlib? Я попытался объединить zlib и http.ServerRequest, и он с треском провалился.
Спасибо!
6 ответов
Вы можете просто объединить request
а также zlib
с потоками.
Вот пример, предполагающий, что у вас есть сервер, слушающий порт 8000:
var request = require('request'), zlib = require('zlib');
var headers = {
'Accept-Encoding': 'gzip'
};
request({url:'http://localhost:8000/', 'headers': headers})
.pipe(zlib.createGunzip()) // unzip
.pipe(process.stdout); // do whatever you want with the stream
Для тех, кто сталкивался с этим в последнее время, библиотека запросов теперь поддерживает распаковку gzip из коробки. Используйте следующим образом:
request(
{ method: 'GET'
, uri: 'http://www.google.com'
, gzip: true
}
, function (error, response, body) {
// body is the decompressed response body
console.log('server encoded the data as: ' + (response.headers['content-encoding'] || 'identity'))
console.log('the decoded data is: ' + body)
}
)
Читайте на github https://github.com/request/request
gzip - если true, добавьте заголовок Accept-Encoding для запроса сжатых кодировок контента с сервера (если он еще не существует) и декодируйте поддерживаемые кодировки контента в ответе. Примечание. Автоматическое декодирование содержимого ответа выполняется для данных тела, возвращаемых через запрос (как через поток запроса, так и передается в функцию обратного вызова), но не выполняется в потоке ответа (доступном из события ответа), который является неизмененным http..IncomingMessage объект, который может содержать сжатые данные. Смотрите пример ниже.
Вот рабочий пример, который стреляет из ответа
function gunzipJSON(response){
var gunzip = zlib.createGunzip();
var json = "";
gunzip.on('data', function(data){
json += data.toString();
});
gunzip.on('end', function(){
parseJSON(json);
});
response.pipe(gunzip);
}
Полный код: https://gist.github.com/0xPr0xy/5002984
Ознакомьтесь с примерами на http://nodejs.org/docs/v0.6.0/api/zlib.html
zlib теперь встроен в узел.
Все ответы здесь не сработали, и вместо этого я получал необработанные байты, а gzip
флаг тоже не работал. Как оказалось, вам нужно установить кодировку наnull
чтобы запросы не преобразовывали ответ в кодировку utf-8 и вместо этого сохраняли двоичный ответ.
const request = require("request-promise-native");
const zlib = require("zlib");
const url = getURL("index.txt");
const dataByteBuffer = await request(url, { encoding: null });
const dataString = zlib.gunzipSync(response);
Заглянув внутрь исходного кода - вы должны установить gzip
param по запросу сам lib для работы gzip. Не уверен, было ли это намеренно или нет, но это текущая реализация. Никаких дополнительных заголовков не требуется.
var request = require('request');
request.gzip = true;
request({url: 'https://...'}, // use encoding:null for buffer instead of UTF8
function(error, response, body) { ... }
);
//functions.js:
var ce=require('cloneextend');
//console.log({aa:'bb',dd:new Date('10/10/2011')});
//console.log(ce.clone({aa:'bb',dd:new Date('10/10/2011')}));
exports.cloneextend=ce;
exports.clone=ce.clone;
exports.extend=ce.extend;
////////////request
var request1=require('request');
var Iconv=require('iconv').Iconv;
var iconv_utf8_to_latin = new Iconv('utf-8','iso-8859-1');
var iconv_iso8859_8i_to_utf8 = new Iconv('iso-8859-8','utf-8');
var iconv_utf8_to_iso8859_8i = new Iconv('utf-8','iso-8859-8');
exports.iconv_iso8859_8i_to_utf8=iconv_iso8859_8i_to_utf8;
exports.iconv_utf8_to_iso8859_8i=iconv_utf8_to_iso8859_8i;
var zlib=require('zlib');
function request_unzip(options,cb)
{
var enc=options.encoding;
options.encoding=null;
var r=request1(options)
.on('response',function(response)
{
var bufarr=[];
var errored=false;
switch (response.headers['content-encoding'])
{
// or, just use zlib.createUnzip() to handle both cases
case 'gzip':
case 'deflate':
if(response.headers['content-encoding']=='gzip')
var zpipe=zlib.createGunzip();
else
var zpipe=zlib.createInflate();
zpipe
.on('data', function(d){bufarr.push(d);})
.on('end', function(){ if(errored) return;errored=true; cb(null,response, enc?Buffer.concat(bufarr).toString(enc):Buffer.concat(bufarr) ); })
.on('error', function(err){ if(errored) return;errored=true; cb(err,response,null);});
response.pipe(zpipe);
response
.on('error', function(err){ if(errored) return;errored=true; cb(err,response,null);});
break;
default:
response
.on('data', function(d){bufarr.push(d);})
.on('end', function(){ if(errored) return;errored=true; cb(null,response, enc?Buffer.concat(bufarr).toString(enc):Buffer.concat(bufarr) ); })
.on('error', function(err){ if(errored) return;errored=true; cb(err,response,null);});
break;
}
});
return r;
}
function request(options,cb)// a request that fixes encoding
{
if(options.encoding=='iso-8859-8')
{
options.encoding='binary';
return request_unzip(options, function(error,request,data){
if(data===undefined||data===null)
{
data2=null;
cb(error,request,data2);
}
else
{
try{
cb(error,request,
iconv_iso8859_8i_to_utf8.convert(iconv_utf8_to_latin.convert(data)).toString('utf8') //conver buffer to string
);
}
catch(e)
{
data2=null;
error=e;
cb(error,request,data2);
}
}
});
}
else
return request_unzip(options,cb);
}
request.__proto__=request1;
exports.request=request;
ie9headers= // no var goes to global
{
followAllRedirects:true,
headers:
{
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "he-IL,he;q=0.8,en-US;q=0.6,en;q=0.4",
"User-Agent": "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22",//"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0)",
"Accept-Charset": "windows-1255,utf-8;q=0.7,*;q=0.3",
"Accept-Encoding": "gzip,deflate,sdch"
}
}
///
example:
f=require('./function.js'); //goes global
function getsomething(cb){
function getit(){
f.request(f.extend({jar:j,url:myurl, headers:{Referer:url}, encoding:'UTF-8' },ie9headers),function(error,request,data)
{
if(error) setTimeout(getit,1000);
//console.log("data",data);
var parsed=myparse(data);
cb(parsed);
});}
getit();
}