Discuz! BBS

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 28|回复: 0

Failed to open a WebSocket connection: empty Connection header.

[复制链接]

394

主题

559

帖子

3303

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
3303
发表于 4 天前 | 显示全部楼层 |阅读模式
您遇到的错误信息表明您尝试用 curl 直接访问 WebSocket 服务器,但 WebSocket 协议需要特殊的握手过程,而普通 HTTP 客户端(如 curl 或浏览器)无法直接完成这个协议升级过程。以下是详细分析和解决方案:
1. 错误原因分析
  • [size=0.8125]WebSocket 协议特性
    WebSocket 连接需要从 HTTP 升级而来,客户端必须发送带有 Upgrade: websocket 和 Connection: Upgrade 头的特殊 HTTP 请求。普通 HTTP 客户端(如 curl)默认不会发送这些头信息。
  • [size=0.8125]curl 的默认行为
    当您执行 curl http://localhost:2700 时:
    • curl 发送的是普通 HTTP GET 请求
    • 服务器期望收到 WebSocket 握手请求
    • 由于缺少必要头信息,服务器拒绝连接
    • 返回的错误信息中明确提示:"You cannot access a WebSocket server directly with a browser"

2. 正确测试方法方案1:使用 WebSocket 专用客户端工具
推荐使用以下工具测试 WebSocket 连接:
工具名称
安装命令(Linux)
使用示例

websocat
sudo apt install websocat
websocat ws://localhost:2700

wscat
npm install -g wscat
wscat -c ws://localhost:2700

示例(使用 websocat):
  1. echo "test message" | websocat ws://localhost:2700
复制代码
方案2:使用 curl 的 WebSocket 模式(需要 7.66.0+ 版本)
如果您坚持使用 curl,需要指定 WebSocket 模式:
  1. curl --include \
  2.      --no-buffer \
  3.      --header "Connection: Upgrade" \
  4.      --header "Upgrade: websocket" \
  5.      --header "Host: localhost:2700" \
  6.      --header "Sec-WebSocket-Version: 13" \
  7.      --header "Sec-WebSocket-Key: $(openssl rand -hex 16)" \
  8.      http://localhost:2700
复制代码
方案3:修改服务器代码添加调试端点
建议在服务器端添加一个普通 HTTP 端点用于调试:
  1. from fastapi import FastAPI
  2. from fastapi.websockets import WebSocket, WebSocketDisconnect
  3. import uvicorn

  4. app = FastAPI()

  5. @app.get("/")
  6. async def health_check():
  7.     return {"status": "ok", "protocol": "WebSocket server is running"}

  8. @app.websocket("/ws")
  9. async def websocket_endpoint(websocket: WebSocket):
  10.     await websocket.accept()
  11.     try:
  12.         while True:
  13.             data = await websocket.receive_text()
  14.             await websocket.send_text(f"Echo: {data}")
  15.     except WebSocketDisconnect:
  16.         print("Client disconnected")

  17. if __name__ == "__main__":
  18.     uvicorn.run(app, host="0.0.0.0", port=2700)
复制代码

3. 验证步骤
先测试 HTTP 端点:
  1. curl http://localhost:2700/
  2. # 应返回:{"status":"ok","protocol":"WebSocket server is running"}
复制代码
再测试 WebSocket 连接:
  1. websocat ws://localhost:2700/ws
  2. # 输入测试消息后应收到回声响应
复制代码
4. 常见问题排查表
现象
可能原因
解决方案

curl 返回 404
未正确处理 HTTP 请求
添加 /health 等调试端点

连接立即关闭
缺少 Sec-WebSocket-Accept 头
使用专业 WebSocket 客户端

"Connection refused"
服务未运行
检查服务日志 journalctl -u your_service

"Timeout during handshake"
防火墙阻止
检查 iptables/nftables 规则

5. 最佳实践建议
  • 开发环境:始终保留一个 HTTP 调试端点
  • 生产环境
    • 使用 Nginx 作为反向代理处理 WebSocket
    • 配置健康检查端点  (nginx)


  1. location /health {
  2.     return 200 "ok";
  3.     add_header Content-Type text/plain;
  4. }

  5. location /ws {
  6.     proxy_pass http://backend:2700;
  7.     proxy_http_version 1.1;
  8.     proxy_set_header Upgrade $http_upgrade;
  9.     proxy_set_header Connection "Upgrade";
  10. }
复制代码
您当前的错误完全符合预期行为,因为 WebSocket 需要特殊的协议升级流程。建议使用 websocat 或 wscat 进行测试,这些工具会自动处理所有必要的协议头信息。


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|DiscuzX

GMT+8, 2025-10-25 19:51 , Processed in 0.012435 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表