Заключение запроса node.js в обещание и конвейер - PullRequest
0 голосов
/ 28 июня 2018

Вот мой сценарий: Я хочу получить некоторый внешний ресурс (двоичный файл) с помощью библиотеки request и передать его клиенту моего собственного приложения. Если код ответа! = 200 или возникают проблемы с удаленным сервером, я хочу перехватить и вместо этого предоставить пользовательское сообщение об ошибке. В идеале, если ответ в порядке, я хочу, чтобы оригинальные заголовки были сохранены.

Мне удалось достичь этого с помощью первого фрагмента кода, который я вставил ниже. Тем не менее, все мое приложение основано на API Promise, поэтому я хотел сделать его согласованным и обернуть его в обещание. И когда я это делаю, это больше не работает. Во-первых, я пытался добиться этого с request-обещанием , но безуспешно. Затем я попытался самостоятельно подготовить очень простой пример, но все же безуспешно.

Рабочий пример

var r = request.get('http://foo.bar');
r.on('response', result => {
  if (result.statusCode === 200) {
    r.pipe(res);
  } else {
    res.status(500).send('custom error message')
  }
});
r.on('error', error => res.status(500).send('custom error message');

Пример не работает

var r;
return new Promise((resolve, reject) => {
  r = request.get('http://foo.bar');
  r.on('response', result => {
    if (result.statusCode === 200) {
      resolve();
    } else {
      reject()
    }
  });
  r.on('error', reject);
}).then(() => {
  r.pipe(res);
}).catch(() => {
  res.status(500).json('custom error message');
});

Под «не работает» я имею в виду - ответ не доставлен, запрос находится на рассмотрении до истечения времени ожидания.

Я изменил код для вызова .pipe(), если результат передан resolve вместо r. Он отвечает клиенту, но тогда ответ пуст.

В конце я попытался заменить запрос lib просто http.get(). И с этим сервер возвращает файл клиенту, но заголовки (например, Content-Type или Content-Length) отсутствуют.

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

1 Ответ

0 голосов
/ 28 июня 2018

Проблема заключается в том, что при срабатывании "response" вы создаете новое обещание, которое разрешается немедленно, но обратный вызов then всегда выполняется асинхронно, и когда он вызывается, файл поступает на сервер, и возникает нет данных, проходящих через поток больше. Вместо этого вы можете просто использовать параметр body обратного вызова:

request.get('http://foo.bar', function(request, response, body) {
  if(response.statusCode === 200) {
    res.end(body);
  } else {
    res.status(500).end();
  }
});

Для работы с потоками request кажется немного глючным, axios, кажется, делает это лучше:

axios.get("http://foo.bar"', {
  validateStatus: status => status === 200,
  responseType: "stream"
}).then(({data: stream}) => {
  stream.pipe(res);
}).catch(error => {
   res.status(500).json(error);
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...