且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在同一个端口上运行 websocket 和 http 服务器(Rust、hyper)

更新时间:2023-11-22 19:59:34

rust-websocket 文档中似乎有一些关于此的文档 这里

从文档中粘贴:

使用 hyper::server::{Server, Request, Response};使用 websocket::Message;使用 websocket::sync::server::upgrade::IntoWs;使用 websocket::sync::server::upgrade::HyperRequest;服务器::http("0.0.0.0:80").unwrap().handle(move |req: Request, res: Response| {匹配 HyperRequest(req).into_ws() {好的(升级)=>{//`accept` 发送成功的握手,无需担心 res让 mut 客户端 = 匹配 upgrade.accept() {好的(c) =>C,错误(_)=>恐慌!(),};client.send_message(&Message::text("它的免费房地产"));},错误((请求,错误))=>{//继续正常使用请求,echo uri"res.send(b"尝试通过 ws 连接.").unwrap();},};}).解包();

I want to write a webserver using Rust, Hyper and websocket-rs. The webserver must be able to handle http requests AND websocket requests on the same port. I used the official sample (async-server.rs: https://github.com/cyderize/rust-websocket/blob/master/examples/async-server.rs) and tried to modify it. My idea was to change the error handling. If the client's request is a simple http request then do not return an error, but spawn a future which handles the request instead.

Based on another SO question (How do I handle an error when using rust-websocket so that only that connection fails and not the entire program?) I changed the error handling from the sample.

This is the old code:

.map_err(|InvalidConnection {error, ..}| {
    println!("Error:{:?}",error);
    return error;
})

Here is my new code:

.map(Some).or_else(|_| -> Result<_, ()> {
    // SPAWN THE FUTURE
    Ok(None)
})

This is where I am stuck. The sample code calls a function spawn_future, which expects a parameter (upgrade.reject()) which is not available in my code since I do not have access to an upgrade structure. I tried a few other things (i.e. calling handle.spawn_fn) but the compiler never liked what I did. (I could paste some of the compiler errors, but I do not think that they would improve the quality of my post.)

Here is my question: What is the recommended way to write an asynchronous server which can handle http requests AND websocket requests on the same port? If my approach is correct: can you please help me to fill the SPAWN THE FUTURE line?

Additional context (if you haven't noticed yet): I am a total Rust beginner.

There seems to be some docs on this in the rust-websocket documentation here

Pasting from the docs:

use hyper::server::{Server, Request, Response};
use websocket::Message;
use websocket::sync::server::upgrade::IntoWs;
use websocket::sync::server::upgrade::HyperRequest;

Server::http("0.0.0.0:80").unwrap().handle(move |req: Request, res: Response| {
    match HyperRequest(req).into_ws() {
        Ok(upgrade) => {
            // `accept` sends a successful handshake, no need to worry about res
            let mut client = match upgrade.accept() {
                Ok(c) => c,
                Err(_) => panic!(),
            };

            client.send_message(&Message::text("its free real estate"));
        },

        Err((request, err)) => {
            // continue using the request as normal, "echo uri"
            res.send(b"Try connecting over ws instead.").unwrap();
        },
    };
})
.unwrap();