Вопрос или проблема
Узел https & пакет zlib: невозможно разобрать gzip’ированный ответ от stackoverflow.com
gunzip ответа не работает (я точно получаю gzip ответ), заголовки не верные, я действительно не понимаю почему. Вот демонстрационный код ниже:
const https = require('https')
const zlib = require('zlib')
const options = {
headers: {
'Accept-Encoding': 'gzip'
},
}
https.get('https://stackoverflow.com/', options, resp => {
let data = "";
resp.on("data", chunk => {
data += chunk;
});
resp.on("end", () => {
if (resp.headers['content-encoding'] != 'gzip') {
console.log('должен получить gzip')
process.exit(1)
}
console.log('получен gzip!')
zlib.gunzip(data, data_ungzip => {
console.log(data_ungzip)
})
});
})
вывод:
получен gzip!
Ошибка: неверная проверка заголовка
at Zlib.zlibOnError [as onerror] (zlib.js:187:17) {
errno: -3,
code: 'Z_DATA_ERROR'
}
Ответ или решение
Проблема, с которой вы столкнулись, связана с тем, что данные, которые вы получаете из ответа, не являются корректными для использования с методом zlib.gunzip
. В Node.js поток данных, получаемый из HTTP-запроса, не следует сразу же конкатенировать в строку, так как это приводит к некорректному формату данных для распаковки с помощью gunzip
.
Вот решение вашей проблемы:
- Вместо конкатенации данных в строку, вам нужно использовать буфер для аккумулирования получаемых данных.
- После завершения получения всех данных, вы можете использовать
zlib.gunzip
для распаковки этих данных.
Вот исправленный код:
const https = require('https');
const zlib = require('zlib');
const options = {
headers: {
'Accept-Encoding': 'gzip',
},
};
https.get('https://stackoverflow.com/', options, resp => {
const chunks = []; // Массив для хранения данных
resp.on('data', chunk => {
chunks.push(chunk); // Добавляем каждый кусок данных в массив
});
resp.on('end', () => {
// Объединяем все чанки в буфер
const buffer = Buffer.concat(chunks);
// Проверяем, что заголовок контент-кодирования равен 'gzip'
if (resp.headers['content-encoding'] !== 'gzip') {
console.log('Ожидается gzip');
process.exit(1);
}
console.log('Получен gzip!');
// Распаковываем буфер
zlib.gunzip(buffer, (err, data_ungzip) => {
if (err) {
console.error('Ошибка при распаковке:', err);
return;
}
console.log(data_ungzip.toString()); // Выводим результат распаковки
});
});
}).on('error', (err) => {
console.error('Произошла ошибка запроса:', err);
});
В этом коде:
- Мы собираем данные в массив
chunks
и затем объединяем их в одинBuffer
, используяBuffer.concat(chunks)
. - Мы проверяем заголовок
content-encoding
перед распаковкой. - В случае ошибки распаковки, добавлена обработка ошибки для более понятного вывода.
Этот подход позволяет корректно обрабатывать сжатый ответ от сервера, избегая проблем, связанных с неправильным форматом данных.