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

http-proxy-middleware页面阻塞加载问题排查与解决求助

问题分析与解决方案

首先咱们拆解下页面一直加载的核心原因:

你在onProxyRes钩子中重写了res.write、res.writeHead和res.end这几个响应核心方法,拦截了代理服务器原本的响应流程。但关键问题在于:当代理响应的end事件触发(也就是proxyRes.on('end', ...)执行时),你只处理了响应体的buffer,却没有主动调用自己重写后的res.end(),这就导致浏览器一直在等待服务器发送响应结束的信号,自然会一直处于加载阻塞状态。

另外还有两个小细节需要修正:

  • Node.js已经废弃了new Buffer('')写法,建议改用Buffer.from('')
  • 你在proxyRes.on('end')里给body赋值,但在res.end逻辑里却用了buffer.toString(),可以统一逻辑避免混淆

下面是修正后的完整代码,我标注了关键修改点:

var express = require('express');
var http = require('http');
var proxy = require('http-proxy-middleware');

function bodyTransform(body) {
  return body.replace('World', 'People');
}

var onProxyRes = (proxyRes, req, res) => {
  const end = res.end;
  const writeHead = res.writeHead;
  let writeHeadArgs;
  // 替换废弃的Buffer构造函数
  let buffer = Buffer.from('');

  proxyRes.on('data', (chunk) => {
    console.log("inside: .on('data', ...)");
    buffer = Buffer.concat([buffer, chunk]);
  });

  proxyRes.on('end', () => {
    console.log("inside: .on('end', ...)");
    // 关键修改:在这里调用重写后的res.end(),触发最终响应发送
    res.end();
  });

  res.write = () => { };
  res.writeHead = (...args) => { writeHeadArgs = args; };
  res.end = () => {
    const output = bodyTransform(buffer.toString('utf8'));
    res.setHeader('content-length', output.length);
    if (writeHeadArgs) writeHead.apply(res, writeHeadArgs);
    end.apply(res, [output]);
    console.log('after: end.apply(res, [output]);');
  };
}

const portApp01 = 3001;
const app01 = express()
app01.get('/', (req, res) => {
  res.send('Hello World!');
});
app01.listen(portApp01, () => {
  console.log('app01 is listening on port: ' + portApp01);
});

const portProxy = 3002;
const appProxy = express()
appProxy.use(proxy({
  target:'http://localhost:3001',
  onProxyRes: onProxyRes,
  changeOrigin: true
}));
http.createServer(appProxy).listen(portProxy, function () {
  console.log('appProxy is listening on port: ' + portProxy);
});

补充解释之前加return的两种情况:

  • 在res.writeHead = ...前加return:相当于直接跳过了所有响应拦截逻辑,代理服务器会直接把原响应发送给浏览器,所以页面能正常显示,但你的自定义响应体替换逻辑就完全不执行了。
  • 在res.writeHead = ...后加return:你已经重写了响应方法,但没有完成后续的响应发送流程,浏览器还是收不到结束信号,所以页面会永久处于加载状态。

现在运行修正后的代码,页面会正常显示Hello People!,终端日志也会完整输出,不会再出现阻塞问题。

内容的提问来源于stack exchange,提问作者davidesp

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:40:23