修改Nginx处理Open WebUI的WebSocket连接失败问题

问题背景

笔者近期在本地部署了​Open WebUI​,并通过Nginx反向代理将服务暴露到公网。部署完成后,前端页面出现以下关键报错:

浏览器控制台报错​(已脱敏处理):

javascript
WebSocket connection to 'ws://app.example.com/ws/socket.io/?EIO=4&transport=websocket' failed:
doOpen @ websocket.js:43
(anonymous) @ transport.js:46
connect_error @ socket.js:170
xe: websocket error
    at Ie.onError (http://app.example.com/_app/chunks/index.abc123.js:1:6173)
    at ws.onerror (http://app.example.com/_app/chunks/index.abc123.js:1:12730)

关键现象:

普通HTTP请求(如页面加载、API调用)正常
WebSocket握手阶段直接失败,状态码非101 Switching Protocols
控制台明确提示Upgrade头未正确处理

问题定位过程

1. 通过浏览器开发者工具排查

按下 ​F12 打开调试工具,按以下路径分析:

​Network → ​WS 筛选器 → 查看WebSocket请求
目标地址:ws://app.example.com/ws/socket.io/...
状态码:(failed),无具体HTTP响应码
错误详情:Error during WebSocket handshake: Unexpected response code: 200
​Console 面板 → 捕获到connect_error事件,提示协议升级失败

2. Nginx配置初步检查

原始Nginx配置如下:

nginx
server {
    listen 80;
    server_name app.example.com;  # 实际域名已脱敏

    location / {
        proxy_pass http://localhost:7034;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

发现问题:

缺失WebSocket必需的Upgrade和Connection头处理
未强制使用HTTP/1.1协议
完整解决方案

1. 修改后的Nginx配置

server {
    listen 80;
    server_name app.example.com;  # 示例域名,实际需替换

    location / {
        proxy_pass http://localhost:7034;
        # 基础代理标头
        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_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket核心配置
        proxy_http_version 1.1;          # 强制HTTP/1.1协议
        proxy_set_header Upgrade $http_upgrade;  # 传递协议升级请求
        proxy_set_header Connection "upgrade";   # 保持长连接
        
        # 长连接超时优化(适合Open WebUI高频交互场景)
        proxy_read_timeout 7d;      # 7天无操作断开
        proxy_send_timeout 7d;
    }
}

2. 配置生效命令

sudo nginx -t         # 验证语法
sudo nginx -s reload  # 热重载配置

核心配置解析

配置指令功能描述必要性
proxy_http_version 1.1强制使用HTTP/1.1协议必需
proxy_set_header Upgrade转发协议升级请求必需
proxy_set_header Connection保持长连接状态必需