rust 如何使用tungstenite-rs设置自定义http头?

a0zr77ik  于 2023-10-20  发布在  其他
关注(0)|答案(1)|浏览(155)

我需要监听一个WebSocket,但是,为了让WebSocket工作,在请求过程中必须设置一些http头。
我试图在docs.rs和github issues上搜索任何有用的信息,但我找不到任何有用的信息。

izkcnapc

izkcnapc1#

所以,这个issue #92为我指出了正确的方向。首先,tungsteniteconnect方法接受一个泛型参数,带有trait约束IntoClientRequest。按照这种逻辑添加自己的头文件的最简单方法是使用http crate,因为它的请求类型实现了上述trait。
将此添加到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返回它。这就是:

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路由器至少。

相关问题