我需要监听一个WebSocket,但是,为了让WebSocket工作,在请求过程中必须设置一些http头。我试图在docs.rs和github issues上搜索任何有用的信息,但我找不到任何有用的信息。
izkcnapc1#
所以,这个issue #92为我指出了正确的方向。首先,tungstenite的connect方法接受一个泛型参数,带有trait约束IntoClientRequest。按照这种逻辑添加自己的头文件的最简单方法是使用http crate,因为它的请求类型实现了上述trait。将此添加到cargo.toml:
tungstenite
connect
IntoClientRequest
http
cargo.toml
tungstenite = "0.20.1" http = "0.2.9"
然后创建一个带有header的新请求:
use tungstenite::handshake::client::generate_key; let req = http::Request::builder() .uri("wss://some.uri/path") .header("Sec-WebSocket-Protocol", self.protocol.to_string()) .header("Sec-WebSocket-Key", generate_key());
现在,这通常应该可以工作,但我的解决方案还需要实现IntoClientRequest并构建它,因为出于某种原因,钨不附带构建器。我的解决方案所做的就是创建与上面所示相同的构建器,将其转换为tungsteniteRequest类型,并从IntoClientRequest trait返回它。这就是:
Request
use std::str::FromStr; use http::{Uri, Version}; use tungstenite::{client::IntoClientRequest, handshake::client::generate_key}; pub struct WampRequest<T: ToString> { pub uri: T, pub protocol: T } impl<T: ToString> IntoClientRequest for WampRequest<T> { fn into_client_request(self) -> tungstenite::Result<tungstenite::handshake::client::Request> { let uri = Uri::from_str(&self.uri.to_string())?; let req = http::Request::builder() .uri(self.uri.to_string()) .version(Version::HTTP_11) .header("Sec-WebSocket-Protocol", self.protocol.to_string()) .header("Sec-WebSocket-Key", generate_key()) .header("Connection", "Upgrade") .header("Upgrade", "websocket") .header("Sec-WebSocket-Version", 13) .header("Host", uri.host().unwrap()); Ok(tungstenite::handshake::client::Request::from(req.body(())?)) } }
编辑:有一件事我直到运行时才意识到,如果你这样做,tungstenite不会添加Sec-Websocket-Key,所以我编辑了代码来展示如何手动添加Sec-Websocket-Key,谢天谢地,钨岩使该接口公开。因此,如果您不添加该标头,这将不起作用。编辑2:就像我的第一次编辑一样,我遇到了更多的运行时错误,但现在我可以100%肯定地说,提供的代码至少适用于我个人的用例。具体来说,有恐慌,因为WebSocket协议要求值存在,但它不会自动创建它们,当你创建自己的头,你必须添加它们,我的实现工作的版本1 WAMP路由器至少。
Sec-Websocket-Key
1条答案
按热度按时间izkcnapc1#
所以,这个issue #92为我指出了正确的方向。首先,
tungstenite
的connect
方法接受一个泛型参数,带有trait约束IntoClientRequest
。按照这种逻辑添加自己的头文件的最简单方法是使用http
crate,因为它的请求类型实现了上述trait。将此添加到
cargo.toml
:然后创建一个带有header的新请求:
现在,这通常应该可以工作,但我的解决方案还需要实现
IntoClientRequest
并构建它,因为出于某种原因,钨不附带构建器。我的解决方案所做的就是创建与上面所示相同的构建器,将其转换为tungstenite
Request
类型,并从IntoClientRequest
trait返回它。这就是:编辑:有一件事我直到运行时才意识到,如果你这样做,
tungstenite
不会添加Sec-Websocket-Key
,所以我编辑了代码来展示如何手动添加Sec-Websocket-Key
,谢天谢地,钨岩使该接口公开。因此,如果您不添加该标头,这将不起作用。编辑2:就像我的第一次编辑一样,我遇到了更多的运行时错误,但现在我可以100%肯定地说,提供的代码至少适用于我个人的用例。具体来说,有恐慌,因为WebSocket协议要求值存在,但它不会自动创建它们,当你创建自己的头,你必须添加它们,我的实现工作的版本1 WAMP路由器至少。