phpEnv中Nginx默认不转发WebSocket,因其将所有请求交由PHP-FPM处理;需在location中配置proxy_pass及proxy_http_version 1.1、Upgrade和Connection头透传,且Nginx版本不低于1.12.0。

phpEnv里Nginx默认不转发WebSocket连接
phpEnv套件(如phpEnv-NT、phpEnv-XAMPP变种)默认的 nginx.conf 把所有请求都走 fastcgi_pass 到 PHP-FPM,而 WebSocket 协议(ws:// 或 wss://)必须由 Nginx 以反向代理方式透传,不能经由 PHP-FPM 处理——否则会直接返回 HTTP 400 Bad Request 或卡在 Upgrade 失败。
关键点在于:WebSocket 连接建立时客户端会发 Upgrade: websocket 和 Connection: Upgrade 头,Nginx 必须显式允许并透传,否则直接拒绝或降级为普通 HTTP。
proxy_pass 要配对升级头和长连接
在 phpEnv 的 nginx/conf/vhosts/xxx.conf(或主 nginx.conf 的 server 块内)添加 location 匹配 WebSocket 路径(例如 /ws 或 /api/ws),然后配置如下:
location /ws/ {
proxy_pass http://127.0.0.1:8080; # 后端 WebSocket 服务地址
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 86400; # 防止空闲断连
}注意几个易错项:
立即学习“PHP免费学习笔记(深入)”;
-
proxy_http_version 1.1缺失 → WebSocket Upgrade 不生效 -
proxy_set_header Upgrade $http_upgrade写成固定字符串"websocket"→ 服务端收不到原始 Upgrade 值,握手失败 -
proxy_set_header Connection "upgrade"漏掉引号或写成$http_connection→ Nginx 会丢弃该头 - 后端端口(如
:8080)没在 Windows 防火墙/杀软放行 → 连接被静默拒绝,浏览器显示net::ERR_CONNECTION_REFUSED
phpEnv 的 Nginx 版本太老可能不支持 WebSocket 透传
部分老旧 phpEnv 打包的 Nginx 是 1.10.x 或更早版本,虽有 proxy_http_version 1.1,但对 Upgrade 头处理不完善。现象是:首次连接成功,但几秒后自动断开,控制台报 WebSocket is closed before the connection is established。
验证方法:命令行运行 nginx -v,若输出低于 nginx version: nginx/1.12.0,建议手动替换 bin/nginx 为官方编译版(如 1.20+),或改用 phpEnv-NT v2.5+ 等更新维护的分支。
替换后务必执行:nginx -t 检查语法,再 nginx -s reload 生效,不要只重启 phpEnv 控制面板——它不一定触发 Nginx 重载。
前端 ws:// 地址要跟 Nginx server_name 和 SSL 状态对齐
浏览器同源策略限制严格:如果 Nginx 配了 server_name example.com 且启用了 HTTPS,但前端连的是 ws://localhost:8080,必然跨域失败;反过来,Nginx 走 HTTP 但前端用 wss://,也会被拒绝。
推荐做法:
- 开发时统一用
ws://localhost/ws/,Nginxserver_name localhost,不启用 SSL - 上线时 Nginx 开启 SSL,前端改为
wss://yourdomain.com/ws/,且证书必须有效(自签名证书会被浏览器拦截 WebSocket) - 避免在
location里用rewrite改写路径后再proxy_pass—— WebSocket 的Sec-WebSocket-Key等头可能被破坏
真正麻烦的不是配置本身,而是 phpEnv 把 Nginx、PHP、MySQL 全塞进一个托盘图标里,出问题时你不知道该查 Nginx error.log、PHP-FPM log 还是后端服务日志。先看 nginx/logs/error.log 里有没有 upstream prematurely closed connection 或 client intended to send too large chunked body,再决定往哪边挖。



















