必须启用的Apache模块是mod_proxy.so和mod_proxy_http.so;若后端为HTTPS还需mod_proxy_connect.so,WebSocket代理则额外需mod_proxy_wstunnel.so。

能访问,但必须手动启用 proxy 模块、配置 VirtualHost、且 Node.js 不能监听 80 端口——否则直接报错或 404。
必须启用的 Apache 模块有哪些
Apache 默认禁用所有代理能力,mod_proxy.so 和 mod_proxy_http.so 是最低要求;缺一不可。打开 XAMPP\apache\conf\httpd.conf,确认以下两行前面没有 #:
LoadModule proxy_module modules/mod_proxy.soLoadModule proxy_http_module modules/mod_proxy_http.so
若 Node.js 后端是 HTTPS(如 https://localhost:3001),还需启用:
LoadModule proxy_connect_module modules/mod_proxy_connect.so- 并在
VirtualHost中加SSLProxyEngine on
改完保存,重启 Apache;验证是否生效:在终端运行 httpd -M | findstr proxy(Windows)或 httpd -M | grep proxy(macOS/Linux),看到 proxy_module 和 proxy_http_module 均为 (shared) 才算成功。
反向代理规则必须写在 httpd-vhosts.conf 里
不要往 httpd.conf 底部硬塞 ProxyPass,容易污染主配置、难维护。正确位置是 XAMPP\apache\conf\extra\httpd-vhosts.conf,新增一个 块:
<virtualhost>
ServerName node.local
ProxyPreserveHost On
ProxyPass /api/ http://localhost:3000/api/
ProxyPassReverse /api/ http://localhost:3000/api/
</virtualhost>
关键点:
-
ProxyPreserveHost On:确保 Node.js 收到的Host头仍是node.local,不是localhost:3000,否则路由或重定向会出错 -
/api/末尾斜杠必须严格对齐——ProxyPass /api/对应http://localhost:3000/api/;若目标地址不带斜杠,/api/user会被拼成/apiuser,直接 404 -
ProxyPassReverse必须与ProxyPass完全一致:它负责重写响应头里的Location、Set-Cookie等 URL,否则重定向会跳到localhost:3000
Node.js 必须先跑在非 80 端口,且不能用 XAMPP Shell 启动
Apache 已占 :80,Node.js 再调 app.listen(80) 必然失败,报 EADDRINUSE。必须让 Node.js 监听其他端口(如 3000、5000):
- 启动命令用系统 CMD 或 PowerShell,别用 XAMPP 控制面板自带的 Shell——它不加载你的系统
PATH,node命令会找不到 - 验证 Node.js 是否真在跑:
curl http://localhost:3000/health(假设有该接口),返回正常才继续 - 再测代理层:
curl http://node.local/api/health,若返回同内容,说明代理通了
最后别忘了配 hosts:编辑 C:\Windows\System32\drivers\etc\hosts,加一行 127.0.0.1 node.local,否则浏览器根本解析不了这个域名。
WebSocket 代理要额外启用 mod_proxy_wstunnel
如果 Node.js 提供的是 ws:// 接口(比如 Socket.IO),普通 ProxyPass 会卡在握手阶段。必须启用:
-
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so(在httpd.conf中取消注释) - 配置时路径需明确指向
ws://协议:ProxyPass /ws/ ws://localhost:3000/ws/ - 仍需保留
ProxyPreserveHost On和ProxyPassReverse /ws/ ws://localhost:3000/ws/
最容易被忽略的是:模块启用后没重启 Apache,或者 WebSocket 配置里漏了 wss? 协议前缀,导致连接直接被拒绝而非超时。











