必须启用mod_proxy_wstunnel模块才能代理websocket,否则proxypass ws://会返回500错误或连接重置;需先加载mod_proxy再加载mod_proxy_wstunnel,且listen端口须与virtualhost一致,并补全upgrade/connection头以支持wss。

必须启用 mod_proxy_wstunnel 才能代理 WebSocket
Apache 默认不加载 WebSocket 反向代理模块,直接配 ProxyPass /ws/ ws://127.0.0.1:8081/ws/ 会返回 500 错误或连接被重置。你得手动打开 httpd.conf,找到这两行并去掉注释:
LoadModule proxy_module modules/mod_proxy.soLoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
注意顺序:必须先加载 mod_proxy,再加载 mod_proxy_wstunnel,否则 Apache 启动失败。改完后务必重启 XAMPP 的 Apache 服务,用 httpd -t(在 XAMPP 安装目录的 apache/bin 下执行)验证配置语法是否正确。
Listen 和 VirtualHost 必须端口一致且显式声明
很多人只改了 httpd-vhosts.conf 里的 <virtualhost></virtualhost>,却忘了在 httpd.conf 里加 Listen 8443,结果浏览器访问 wss://localhost:8443 直接 Connection Refused。XAMPP 不会自动监听你写在 vhost 里的任意端口。
- 编辑
apache/conf/httpd.conf,搜索Listen 80,在其下方新增一行:Listen 8443 - 确保
httpd-vhosts.conf中对应 vhost 的端口与之完全一致:<virtualhost></virtualhost> - 如果要用 HTTPS + WSS,还需配置 SSL 模块和证书路径(
SSLEngine on、SSLCertificateFile等),否则 Apache 无法响应 TLS 握手
WSS 要求前端 URL 协议、端口、域名三者严格匹配后端代理目标
浏览器拒绝建立 WSS 连接,最常见的原因是协议升级头没传全,或者后端服务本身没跑在 HTTPS 上。比如你在 vhost 里写:
ProxyPass /ws/ ws://127.0.0.1:9501/ws/ ProxyPassReverse /ws/ ws://127.0.0.1:9501/ws/
这只能支持 ws://,不是 wss://。要走 WSS,后端服务必须本身支持 TLS(如 Swoole 开启 ssl 选项),或你改用 wss:// 代理(但要求后端也配了证书)。更现实的做法是:保持后端用 ws://127.0.0.1:9501,让 Apache 处理 TLS 终结,这时必须补全升级头:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
ProxyPreserveHost OnProxyRequests OffProxyVia Off-
RequestHeader set X-Forwarded-Proto "https"(可选,用于后端识别协议)
否则客户端发起 WSS 握手时,Apache 不转发 Upgrade: websocket 和 Connection: Upgrade,连接就卡在 HTTP 阶段。
本地开发时 WSS 证书不能跳过,但可用自签名 + 浏览器临时信任
XAMPP 自带的 openssl.cnf 和 makecert.bat 可生成本地证书,但 Chrome/Firefox 对自签名证书限制极严——即使你把证书导入系统信任库,wss://localhost:8443 仍可能报 ERR_SSL_PROTOCOL_ERROR。根本原因不是证书无效,而是浏览器要求 WSS 的 SNI 主机名必须匹配证书 Subject Alternative Name(SAN),而默认生成的证书往往只含 CN,不含 SAN。
解决办法只有两个:
- 用 OpenSSL 手动生成含 SAN 的证书(需修改配置、指定
-extfile) - 改用
localhost域名 + 本地 DNS 绑定 + Let’s Encrypt 的localtest.me类域名(如myapp.localtest.me),再申请真实证书
别试图用 chrome://flags/#unsafely-treat-insecure-origin-as-secure 临时绕过——它对 WSS 无效,且新版 Chrome 已移除此 flag。










