Способы сбоя http-запроса после отправки заголовка ответа 200 - PullRequest
0 голосов
/ 04 февраля 2019

Краткий вопрос:

Рассмотрим случай длительных ответов, когда требуется отправить много данных.Затем сервер должен передать данные обратно клиенту, прежде чем завершить генерацию всех данных.Это требует отправки заголовков http в самом начале, если я прав.Но если во время потоковой передачи данных возникает исключение, каков наилучший способ сообщить об этом клиенту?В идеале мне бы хотелось, чтобы XMLHttpRequest в браузере не работал с кодом ответа не-200 или чем-то подобным.Я использую nodejs express на сервере.

Подробный вопрос:

Мне нужно передать в браузер много данных, около 700 Мб.Мне нужно передавать данные клиенту во время генерации данных, а не буферизовать их на сервере, потому что в противном случае серверу не хватит памяти.

Вот код, который я использую на стороне браузера,

return new Promise((resolve, reject) => {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', this.getDownloadLink(), true);
  xhr.setRequestHeader('authorization', this.getAuthToken());
  xhr.responseType = 'blob';
  xhr.onload = () => {
    if (xhr.status === 200) {
      saveAsFile(xhr.response);
      resolve();
    }
    else {
      reject(xhr.response);
    }
  };
  xhr.onerror = () => {
    reject(xhr.response);
  };
  xhr.send();
});

Я использую XHR, потому что мне нужно установить заголовок авторизации.Браузер в порядке с сохранением 700 Мбайт перед сохранением файла, вероятно, потому что он хранит BLOB-объекты на диске, это не блокиратор.

Поэтому я начинаю передачу, не зная, что это закончится успехом.Тогда как мне сообщить об ошибке от сервера клиенту, если в середине произойдет сбой генерации данных? Я бы хотел, чтобы приведенное выше обещание было отклонено при сбое сервера.

Вот часть кода, которую я использую на сервере:

response.status(200);
db.stream
.on('data', data => response.write())
.on('error', error => {
  // this does not work as intended
  response.status(500);
  response.end(error.message);
})

Как вы можетевидите, данные передаются после отправки заголовков.

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Существует способ отправки «заголовков» в конце ответа.Они называются Трейлеры .

Вы можете отправить их, используя nodejs Объект ответа .

0 голосов
/ 04 февраля 2019

Заголовки отправлены и все, без поворота.Клиент не получает весь HTTP-ответ за 700 Мб одновременно, он получает его по частям.Если мы читаем http-ответ как открытый текст, первой его частью будут метаданные (статус и т. Д.) И сами заголовки строка за строкой.По этой причине невозможно отправить статус 500 после того, как вы уже отправили 200. Не потому, что Node.js или express не позволяют этого, а потому, что сам протокол http как протокол связи не позволяет этого.Я вижу, что вы используете http для передачи этого объема данных, потому что вам нужен заголовок для вашей бизнес-логики.Я рекомендую вам взглянуть на socket.io.Это позволяет вам взять некоторую полезную информацию / данные из строки запроса, где вы можете поместить свои данные, для которых вы используете заголовок, в качестве параметра запроса и получить к ним доступ через узел socket.io api!Довольно удобно для выполнения любой аутентификации или связанных вещей.Надеюсь, я тебе помог!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...