如何将一个POST请求转发到两个外部URL?

时间:2017-08-28 03:17:15

标签: javascript node.js http express ecmascript-6

我们使用的一个SaaS提供商有一个webook字段,但只允许输入一个网址。事实上,我们需要将此webhook发送到两个分析服务,因此我需要找到一种方法来编写一个自定义端点,将整个请求转发给我们需要的许多其他端点(目前为2个)。

使用node和express执行此操作的最简单方法是什么?如果我没有弄错,简单的重定向不适用于多个POST,对吗?

我不确定标题甚至是请求内容的样子,但是如果auth在标题等中,则需要尽可能地保留它。

这是我到目前为止所做的,但它还远没有完成:

app.post('/', (req, res) => {
console.log('Request received: ', req.originalUrl)
const forwardRequests = config.forwardTo.map(url => {
  return new Promise((resolve, reject) => {
    superagent
      .post(url)
      .send(req)
      .end((endpointError, endpointResponse) => {
        if (endpointError) {
          console.error(`Received error from forwardTo endpoint (${url}): `, endpointError)
          reject(endpointError)
        } else {
          resolve(endpointResponse)
        }
      })
  })
})
Promise.all(forwardRequests)
  .then(() => res.sendStatus(200))
  .catch(() => res.sendStatus(500))
})

我收到错误,因为superagent.send仅用于内容...我如何完全复制请求并将其发送

1 个答案:

答案 0 :(得分:1)

完全复制请求并将其发送到各个端点,您可以将request模块与req.pipe(request(<url>))Promise.all一起使用。

根据请求模块的文件:

  

您还可以从http.ServerRequest实例以及http.ServerResponse实例中使用pipe()。将发送HTTP方法,标头和实体主体数据。

以下是一个例子:

const { Writable } = require('stream');
const forwardToURLs = ['http://...','http://...'];
app.post('/test', function(req, res) {
  let forwardPromiseArray = [];
  for (let url of forwardToURLs) {
    let data = '';
    let stream = new Writable({
      write: function(chunk, encoding, next) {
        data += chunk;
        next();
      }
    });
    let promise = new Promise(function(resolve, reject) {
      stream.on('finish', function() {
        resolve(data);
      });
      stream.on('error', function(e) {
        reject(e);
      });
    });
    forwardPromiseArray.push(promise);
    req.pipe(request(url)).pipe(stream);
  }

  Promise.all(forwardPromiseArray).then(function(result) {
    // result from various endpoint, you can process it and return a user-friendly result.
    res.json(result);
  }).catch(function() {
    res.sendStatus(500);
  });
});

请注意,上述代码应放在body-parser之前(如果您使用它)。否则,请求将不会通过管道传输。