节点 http-proxy:请求的异步修改 body

node http-proxy: async modification of request body

我需要异步修改请求body。大致是这样的:

proxy.on('proxyReq', function(proxyReq, req, res, options) {
  if(req.body) {
    new Promise(function(resolve){ 
      setTimeout(function() { // wait for the db to return
        'use strict';
        req.body.text += 'test';
        let bodyData = JSON.stringify(req.body);
        proxyReq.setHeader('Content-Type','application/json');
        proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
        // stream the content
        proxyReq.write(bodyData);
        resolve();
      },1);
    });
  }
});

当我 运行 时,我收到错误消息说不能修改 headers 一旦它们被设置。这是有道理的。

如何在我准备好之前停止发送请求?我研究过从 proxyReq 中删除各种侦听器,但没有成功。

通过查看 source code @-) 似乎不太可能,因为发送 proxyReq 事件然后代码继续。

如果它改为等待 promise,那将是可能的(如果您也 return 那个 promise)。

这个库的最小分支可以是例如:

// Enable developers to modify the proxyReq before headers are sent
proxyReq.on('socket', function(socket) {
  if(server) { server.emit('proxyReq', proxyReq, req, res, options); }
});

(proxyReq.proxyWait || Promise.resolve())
    .then( ... // rest of the code inside the callback 

然后

proxy.on('proxyReq', function(proxyReq, req, res, options) {
  if(req.body) {
    proxyReq.proxyWait = new Promise(function(resolve){ 
      setTimeout(function() { ...

但根据您的用例,可能还有其他解决方案。例如,考虑是否真的有必要使用这个代理库。您也可以直接使用 http,您可以在其中控制事件和回调。

可以在HttpProxy.createProxyServer里面设置selfHandleResponse: true。然后,这允许(并强制)您手动处理 proxyRes

const proxy = HttpProxy.createProxyServer({selfHandleResponse: true});
proxy.on('proxyRes', async (proxyReq, req, res, options) => {
  if (proxyReq.statusCode === 404) {
    req.logger.debug('Proxy Request Returned 404');
    const something = await doSomething(proxyReq);
    return res.json(something);
  }
  return x;// return original proxy response
});

我来这里是为了寻找一个稍微不同的问题的解决方案:在代理之前修改请求 headers(不是 body)。

我post这里是希望对其他人有帮助。也许代码也可以修改以修改请求正文。

const http = require('http');
const httpProxy = require('http-proxy');

var proxy = httpProxy.createProxyServer({});

var server = http.createServer(function(req, res) {
    console.log(`${req.url} - sleeping 1s...`);
    setTimeout(() => {
        console.log(`${req.url} - processing request`);
        req.headers['x-example-req-async'] = '456';
        proxy.web(req, res, {
            target: 'http://127.0.0.1:80'
        });
    }, 1000);
});

server.listen(5050);