You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用http-proxy-middleware时onProxyReq钩子未触发的问题求助

使用http-proxy-middleware时onProxyReq钩子未触发的问题求助

我正在用Node.js、Express和http-proxy-middleware搭建一个API网关,根据动态路由逻辑将请求转发到不同的后端服务。之前遇到过目标服务器返回408请求超时的问题,排查后发现是请求体没有被正确发送导致的,于是改用req.rawBody + streamifier.createReadStream()的方式来处理请求体,现在超时问题已经解决了,但新的困扰出现了——onProxyReq钩子完全没有被触发!

我的关键代码片段:

首先是获取原始请求体的中间件,用来确保请求体不会被Express默认中间件吞掉:

// app.js 中获取原始请求体的中间件
app.use(async (req, res, next) => {
  if (['POST', 'PUT', 'PATCH'].includes(req.method)) {
    try {
      req.rawBody = await getRawBody(req);
      if (req.headers['content-type']?.includes('application/json')) {
        req.body = JSON.parse(req.rawBody.toString());
      }
    } catch (err) {
      return res.status(400).send('Invalid JSON body');
    }
  }
  next();
});

然后是动态路由判断和代理请求的处理逻辑:

// 动态路由中间件
const dynamicRouter = (req, res, next) => {
  const entrypoint = req.path;
  const clientId = req.body?.client;
  if (!clientId || !req.rawBody) {
    return res.status(400).json({ error: 'Missing client_id or raw body' });
  }
  // 示例路由配置
  const proxyRoute = {
    endpointPath: '/api/test',
    targetUrl: 'https://example.com'
  };
  if (entrypoint === proxyRoute.endpointPath) {
    return handleProxyRequest(proxyRoute, req, res, next);
  }
  return res.status(404).json({ message: 'Route not found' });
};

// 代理请求处理函数
const handleProxyRequest = (route, req, res, next) => {
  const { targetUrl, endpointPath } = route;
  console.log(`[GATEWAY] Forwarding ${req.path} to ${targetUrl}${endpointPath}`);
  console.log("Request Body:", req.body); // 这里能正常打印出请求体内容
  const middleware = createProxyMiddleware({
    target: targetUrl,
    changeOrigin: true,
    logLevel: 'debug',
    pathRewrite: () => endpointPath,
    buffer: streamifier.createReadStream(req.rawBody),
    onProxyReq: (proxyReq, req, res) => {
      console.log('✅ onProxyReq is being called'); // 这里完全没有日志输出!
      // 手动处理JSON请求体的逻辑
      if ( 
        req.method === 'POST' && 
        req.headers['content-type']?.includes('application/json') && 
        req.body 
      ) {
        const bodyData = JSON.stringify(req.body);
        proxyReq.setHeader('Content-Type', 'application/json');
        proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
      }
      console.log('Forwarding:', req.method, req.originalUrl);
    },
    onProxyRes: (proxyRes, req) => {
      console.log('onProxyRes is being called'); // 同样没有日志输出
    },
    onError: (err, req, res) => {
      console.error('Proxy error:', err.message);
      if (!res.headersSent) {
        res.status(502).json({ error: 'Bad Gateway' });
      }
    }
  });
  return middleware(req, res, next);
};

我已经排查过的点:

  • req.body能被正确解析并打印,说明请求体的获取和解析都没问题
  • targetUrl和endpointPath都是有效的,目标API确实是可达的(从[GATEWAY] Forwarding...的日志可以确认请求确实被转发了,而且目标API返回了正确的响应)
  • 请求方法是POST,请求头的Content-Type也是application/json
  • 确认没有在之前的中间件中提前发送响应导致请求被终止

现在的状况是,请求能正常转发到目标服务并得到响应,但onProxyReq和onProxyRes钩子好像根本没有被执行过一样,完全看不到对应的日志。有没有大佬遇到过类似的情况?或者能给我指个排查的方向?感激不尽!

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 09:33:02