Https 有没有办法在与hyper相同的端口上运行Tungstenite?

Https 有没有办法在与hyper相同的端口上运行Tungstenite?,https,rust,Https,Rust,我正在尝试为一个简单的浏览器游戏制作一个Rust的web服务器。我希望服务器能够通过HTTPS交付页面,但也能够通过WebSocket进行通信。我计划将此服务器放在Heroku上,但由于每个应用程序只允许一个端口,因此我必须使WebSocket服务器在与其他HTTPS代码相同的端口上运行 看起来是这样,但那个板条箱使用了过时版本的hyper,似乎不再维护。板条箱tokio_tungstenite要更新得多 问题在于hyper和tungstenite都有自己的HTTP协议实现,WebSocket通

我正在尝试为一个简单的浏览器游戏制作一个Rust的web服务器。我希望服务器能够通过HTTPS交付页面,但也能够通过WebSocket进行通信。我计划将此服务器放在Heroku上,但由于每个应用程序只允许一个端口,因此我必须使WebSocket服务器在与其他HTTPS代码相同的端口上运行

看起来是这样,但那个板条箱使用了过时版本的
hyper
,似乎不再维护。板条箱
tokio_tungstenite
要更新得多


问题在于
hyper
tungstenite
都有自己的HTTP协议实现,WebSocket通过HTTP协议运行,无法在两者之间转换。这意味着,一旦HTTPS请求被
hyper
tungstenite
解析,就无法继续由另一部分进行处理,因此您不能真正尝试连接WebSocket并匹配
tungstenite
中的错误,然后通过
hyper
进行处理,您也不能通过
hyper
解析请求,并检查它是否是WebSocket请求并将其发送到
tungstenite
。有什么办法可以解决这个问题吗?

我认为应该可以做到这一点,
tungstenite
tokio tungstenite
允许您指定自定义标题(有帮助函数,前缀为
hdr
),因此根据您使用的
hyper
版本,如果您可以将请求转换为某种形式,当可以提取标题时,您可以将其传递给
tungstenite


您可能还想尝试使用
warp
板条箱,它构建在
hyper
之上,并在引擎盖下使用
tungstenite
作为websocket支持,因此如果您想编写自己版本的
warp
,可以查看源代码(源代码可能包含如何将
hyper
tungstenite
结合使用的提示)。

您可以这样做,但它非常灵活。您必须使用
tokio tungstenite
,自己握手(检查标题,设置响应标题)并在运行时生成一个新的未来,该未来将处理websockets连接在具有最新版本的hyper的请求正文上,然后可以将连接传递到tokio_tungstenite::WebSocketStream::from_raw_socket以将其转换为WebSocket连接

示例处理程序(请注意,这不会完全检查请求头,并假设我们需要升级):

fn websocket(请求)->结果
fn websocket(req: Request<Body>) -> Result<Response<Body>, &'static str> {
    // TODO check other header
    let key = match req.headers().typed_get::<headers::SecWebsocketKey>() {
        Some(key) => key,
        None => return Err("failed to read ws key from headers"),
    };
    let websocket_future = req
        .into_body()
        .on_upgrade()
        .map_err(|err| eprintln!("Error on upgrade: {}", err))
        .and_then(|upgraded| {
            let ws_stream = tokio_tungstenite::WebSocketStream::from_raw_socket(
                upgraded,
                tokio_tungstenite::tungstenite::protocol::Role::Server,
                None,
            );
            let (sink, stream) = ws_stream.split();
            sink.send_all(stream)
                .map(|_| ())
                .map_err(|err| error!("{}", err))
        });
    hyper::rt::spawn(websocket_future);
    let mut upgrade_rsp = Response::builder()
        .status(StatusCode::SWITCHING_PROTOCOLS)
        .body(Body::empty())
        .unwrap();
    upgrade_rsp
        .headers_mut()
        .typed_insert(headers::Upgrade::websocket());
    upgrade_rsp
        .headers_mut()
        .typed_insert(headers::Connection::upgrade());
    upgrade_rsp
        .headers_mut()
        .typed_insert(headers::SecWebsocketAccept::from(key));
    Ok(upgrade_rsp)
}