我用Rust编写了一个WebSocket客户端,使用tokio_tungstenite::tungstenite::http::Request
建立连接,并在ASGI/Daphne 4.0.0开发服务器上运行Django Channels 4服务器。
当我使用当前版本的tokio
(特别是0.20)时,我得到以下错误:
Protocol(InvalidHeader("sec-websocket-key"))
然而,当我将tokio
降级到0.14时,客户端代码运行没有问题,并且WebSocket连接建立并按预期运行。(注意,我还没有尝试过其他版本之间-它只是碰巧,我以前得到了它的工作0.14,只是想升级到最新版本的这个项目,这恰好是0.20)
经过一点阅读,我明白了密钥是建立WebSocket连接的握手的一部分。然而,tungstenite
连接器似乎也应该能够自动生成这个,我不应该在我的头文件中自己设置这个。
这些行可能是最相关的:
let request = Request::builder()
.uri(&uri)
.header("Origin", origin)
.body(()).unwrap();
let res = connect_async(request).await;
match res {
Ok((ws_stream, _)) => {
...
请忽略解包-这不是生产代码,我感兴趣的是在使事情变得更好之前解决技术问题。
我是否应该生成一个键,并在头文件中设置它?有没有办法让tungstenite
在concert中为我做这件事,而我仍然想设置一个Origin
头?还是我忽略了大局
在阅读How to set origin header to websocket client in Rust?之后,我尝试了以下操作:
let request = Request::builder()
.uri(&uri)
.header("Host", host)
.header("Origin", origin)
.header("Connection", "Upgrade")
.header("Upgrade", "websocket")
.header("Sec-WebSocket-Version", "13")
.header("Sec-WebSocket-Key", tokio_tungstenite::tungstenite::handshake::client::generate_key())
.body(()).unwrap();
但这会导致另一个错误,表明服务器对尝试不满意:
Http(Response { status: 400, version: HTTP/1.1, headers: {}, body: Some([]) })
如果我降级到0.14,代码甚至不能工作,因为generate_key()
在那个版本中是私有的,所以似乎tungstenite
不希望我自己调用它(或者至少不习惯)。tokio 0.14
可能做了什么而0.20
没有做的事情,我应该如何解决这个问题?
1条答案
按热度按时间hgtggwj01#
用户@kmdreko仔细查看后发现,可能的罪魁祸首是
"Host"
头字段,它确实是。正在传递字段 *,但没有传递端口号 *。然而,尽管下面的工作,正确的值为
host
:这有点令人不满意,因为所有这些值都有点随意,我想让
tungstenite
提供合理的默认值。这不起作用:
这就是我一直在寻找的解决方案:
通过将
request
定义为可变的,然后在tungstenite
生成的Request
上插入所需的"Origin"
字段,我能够得到一个工作解决方案,其中tungstenite
将所有其他字段设置为所需的默认/当前设置。