Как ограничить размер блока, поступающего с сервера rest в http-модуль nodejs?

#javascript #node.js #stream #node-https

#javascript #node.js #поток #узел-https

Вопрос:

Я запрашиваю сервер rest у nodejs с помощью модуля запроса nodejs. Я хочу отменить поток, если размер входящих данных превышает допустимый предел. цель здесь — убедиться, что моя сеть не заблокирована.

Мой пример кода выглядит следующим образом;

 var http = require("http");

async function httpRequest({
  host,
  method,
  port,
  path
} = params, data) {
  if (method.toUpperCase() === "GET") {
    let query = "";
    data = JSON.parse(data);

    for (var key in data) {
      if (data.hasOwnProperty(key)) {
        let value = data[key];
        console.log(key   " -> "   value);
        query = query
          .concat("amp;")
          .concat(key)
          .concat("=")
          .concat(value);
      }
    }
    if (query) {
      query = "?".concat(query.substring(1));
    }
    path = encodeURI(path.concat(query));
    console.log("path : "   path);
  }
  var opts = {
    hostname: host,
    port: port,
    path: path,
    method: method,
    timeout: 30 * 1000,
    headers: {
      "Content-Type": "application/json"
    }
  };
  return new Promise(function (resolve, reject) {
    const req = http.request(opts, function (response) {
      console.log("Status Code : "   response.statusCode);
      if (response.statusCode < 200 || response.statusCode >= 300) {
        req.end();
        return reject("Fetch data failed  = "   response.statusCode);
      }
      var str = "";
      response.on("data", function (chunk) {
        console.log("chunk : "   chunk);
        str  = chunk;
        if (str.length > 256) {
          req.abort();
          reject(
            new Error(
              "The size of the incoming data is larger than the allowable limit."
            )
          );
        }
      });

      response.on("end", function () {
        console.log("n Result from web service : ", str);
        try {
          let jsonData = JSON.parse(str);
          if (jsonData.status) {
            if (jsonData.status.toLowerCase === "success") {
              if (!("result" in jsonData)) {
                reject("Json Structure Error");
              }
            } else if (jsonData.status.toLowerCase === "error") {
              if (!jsonData.error) {
                reject("Json Structure Error");
              }
            }
            resolve(jsonData);
          } else {
            reject("Json Structure Error");
          }
        } catch (error) {
          reject("Response json error : "   error);
        }
      });
    });

    if (method.toUpperCase() !== "GET" amp;amp; data) {
      req.write(data);
    }
    //req bitti
    req.on("timeout", function () {
      console.log("timeout! "   opts.timeout / 1000   " seconds expired");
      req.abort();
    });

    req.on("error", function (err) {
      console.log("Error : "   err);
      if (err.code === "ECONNRESET") {
        req.abort();
        console.log("Timeout occurs : "   err);
        reject(new Error("Timeout occurs : "   err));
      } else if (err.code === "ENOTFOUND") {
        req.abort();
        console.log("Address cannot be reachable : "   err);
        reject(new Error("Address cannot be reachable : "   err));
      } else {
        req.abort();
        reject(new Error(err));
      }
    });
    req.end();
  });
}

let data = JSON.stringify({
  username: "monetrum",
  password: "123456",
  name: "Loremipsumdolorsitamet,consecteturadipiscingelit"  
    ".Aeneaninaliquamodio,egetfac"
});

let params = {
  host: "127.0.0.1",
  method: "GET",
  port: 3010,
  path: "/login"
};

httpRequest(params, data);
  

Пока все хорошо.Но есть проблема.Я контролирую входящие данные.Разрешенный размер данных не должен превышать 256 байт.Но первая выборка блока больше допустимого размера.Так что мой контроль размера — это ерунда.Есть ли способ справиться с этим.Возможно ли ограничить размер блока. Заранее спасибо.

Ответ №1:

Событие ‘readable’

Вы хотите использовать readable событие вместо data event:

 var byteCount = 0;
var chunkSize = 32;
var maxBytes = 256;

req.on('readable', function () {
  var chunks = [];
  var data;

  while(true) {
    data = this.read(chunkSize);
    if (!data) { break; }

    byteCount  = data.byteLength;
    if (byteCount > maxBytes) {
      req.abort();
      break;
    }

    chunks.push(data);
  }

  // do something with chunks
});

req.on('abort', function () {
  // do something to handle the error
});
  

Поскольку ваш вопрос очень специфичен, я сделал пример немного более общим, так что, надеюсь, другие тоже смогут извлечь из него информацию.

Смотрите https://nodejs.org/api/stream.html#stream_event_readable

Однако…

Сети все равно

Однако вы собираетесь получить больше данных, чем это. Размер TCP-пакета составляет 64 кб. Через негигабитный Ethernet, при котором MTU усекается до 1500 байт (1,5 кбайт).

Вы ничего не можете сделать, чтобы предотвратить сетевую активность, кроме закрытия соединения, и вы не можете получить менее 1,5 тыс. данных за событие data, если только не отправляется менее 1,5 тыс. данных (или возникают сумасшедшие проблемы с сетью, которые вы не можете контролировать).t

P.S.

Я бы рекомендовал вам использовать редактор кода, такой как VSCode. Очень сложно читать код, который содержит сочетания табуляций и пробелов и разные блоки на разных уровнях. Он предложит плагины, которые помогут вам раньше обнаруживать ошибки и переформатировать ваш код, чтобы другим (и вам самим) было легче его читать.

Комментарии:

1. Большое спасибо за ваш ответ. Я не знал свойства readable. Я попытаюсь работать.

2. И спасибо также за ваше предложение. Я уже использую VSCode и Prettier — Code formatter. Но я не понимаю, как это форматируется.

3. Некоторые примечания, вы должны добавить читаемый прослушиватель к разрешению , а не к запросу uest. Кроме того, req.abort() не рекомендуется, используйте req.destroy() .