Как изменить / удалить / игнорировать заголовок http непосредственно перед анализом ответа в Node?

В настоящее время я работаю с Node для получения данных из API (Discogs API), и у меня появляется эта ошибка при запросе:

{ [Error: Parse Error] bytesParsed: 0, code: 'HPE_INVALID_CONSTANT' }

Используя эту ссылку: http://api.discogs.com/releases/249504 (но у меня та же ошибка для всех других запросов, когда content-length != actual content length)

И этот код:

var http  = require('http');

var options = {
  hostname: 'api.discogs.com',
  port: 80,
  path: '/releases/249504',
  method: 'GET'
};

var req = http.request(options, function(res) {
  console.log("statusCode: ", res.statusCode);
  console.log("headers: ", res.headers);

  res.on('data', function(d) {
    console.log(d);
  });
});
req.end();

req.on('error', function(e) {
  console.error(e);
});

Я обнаружил, что значение Content-length всегда меньше реальной длины байта ответа.

Content-length : 2142

Actual Byte Length : 7,734 Bytes (according to https://mothereff.in/byte-counter)

Я читал, что парсер Node действительно строгий, и поэтому он не разбирает ответ.

Наконец, я спрашиваю вас, есть ли способ игнорировать / изменять / удалять заголовок непосредственно перед тем, как Node анализирует ответ, чтобы анализатор мог выполнять свою работу, игнорируя Content-Length?

2 ответа

Решение

Это не связано с (воспринимается, см. Ниже) недопустимой длиной содержимого, поскольку оно также не работает с использованием cURL:

$ curl  http://api.discogs.com/releases/249504
curl: (52) Empty reply from server

Очевидно сервер API требует, чтобы заголовок пользовательского агента был установлен:

var options = {
  hostname : 'api.discogs.com',
  port     : 80,
  path     : '/releases/249504',
  method   : 'GET',
  headers  : { 'user-agent' : 'foo/1.0' }
};

Что касается разницы в длине содержимого: 2142 - это размер сжатого gzip ответа (content-encoding: gzip), 7734 - размер несжатого ответа. Очевидно, ваш тест счетчика байтов запрашивает только несжатые ответы, но клиент, с которым вы проверили заголовок, запрашивает сжатый ответ.

Возвращаясь к теме изменения заголовков непосредственно перед анализом ответа в Node , вы можете легко это сделать, заменив стандартный обработчик своей собственной функцией на socket: "data" мероприятие.

https://github.com/nodejs/http2/blob/master/lib/_http_client.js#L655

      var req = http.request(options, function(res) {
  console.log("statusCode: ", res.statusCode);
  console.log("headers: ", res.headers); // without "Pragma: public" header

  res.on('data', function(d) {
    console.log(d);
  });
});

// catch socket object on conection initialization
req.on('socket', function (socket) {
    // https://nodejs.org/api/events.html
    var standardHandler = socket.listeners('data')[0];
    socket.off('data', standardHandler);

    socket.on('data', function(data) {
        var str = data.toString();
        console.log(str);
        // HTTP/1.x 200 OK
        // Date: Sat, 28 Nov 2009 04:36:25 GMT
        // Connection: close
        // Pragma: public
        // Expires: Sat, 28 Nov 2009 05:36:25 GMT
        // Cache-Control: max-age=3600, public
        // Content-Type: text/html; charset=UTF-8
        // Content-Length: 533424
        // Content-Encoding: gzip
        // Vary: Accept-Encoding, Cookie, User-Agent
        //  
        // <!DOCTYPE html PUBLIC "-//W3C//DTD

        // Do anything you need
        // removing 4 line
        var lines = str.split('\r\n');
        lines.splice(3, 1)
        str = lines.join('\r\n');

        // Now pass new data onto standard request handler
        standardHandler.call(socket, Buffer.from(str, "utf-8"));
    })
});

req.end();
Другие вопросы по тегам