Узел https & пакет zlib: невозможно разобрать gzip’ированный ответ от stackoverflow.com

Вопрос или проблема

Узел 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.

Вот решение вашей проблемы:

  1. Вместо конкатенации данных в строку, вам нужно использовать буфер для аккумулирования получаемых данных.
  2. После завершения получения всех данных, вы можете использовать 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 перед распаковкой.
  • В случае ошибки распаковки, добавлена обработка ошибки для более понятного вывода.

Этот подход позволяет корректно обрабатывать сжатый ответ от сервера, избегая проблем, связанных с неправильным форматом данных.

Оцените материал
Добавить комментарий

Капча загружается...