actix / actix-web

Actix Web is a powerful, pragmatic, and extremely fast web framework for Rust.
https://actix.rs
Apache License 2.0
21.44k stars 1.66k forks source link

actix_web_actors::ws::start don't accept Frame stream #3415

Open alaravel opened 3 months ago

alaravel commented 3 months ago

Hi How I can pass awc stream to actix_web_actors::ws::start? It's expected Result<Bytes, PayloadError> but framed is Result<Frame, ...>

let con=awc::Client::new()
        .ws(url)
        .connect().await;
   match con {
        Ok((mut res,mut framed)) => {
            let req=TestRequest::default()
                .insert_header(("sec-websocket-key",res.headers().get("sec-websocket-accept").unwrap()))
                .insert_header(("sec-websocket-version","13"))
                .insert_header(("connection","upgrade"))
                .insert_header(("upgrade","websocket"))
                .to_http_request();

            match actix_web_actors::ws::start(
                WsSession::new(id,room,addr),
                &req,
                framed //todo
            ){
                Ok(a) => {

                }
                Err(e) => {
                    println!("error ={:?}",e)
                }
            }
        }
        Err(_) => {}
    }

Your Environment

earthskyorg commented 1 month ago

To pass an awc stream to actix_web_actors::ws::start, you need to bridge the gap between the awc WebSocket client's frame-based protocol and the actix_web_actors::ws module's expectations.

earthskyorg commented 1 month ago

Here's a conceptual approach to solve this issue:

Capture Frames from awc: As you've done, capture the frames from the awc WebSocket connection. Convert Frames to Bytes: Manually convert each frame into bytes. This involves encoding the frame according to the WebSocket protocol, which typically uses base64 encoding for binary data. Pass Bytes to actix_web_actors::ws::start: Pass the converted bytes to actix_web_actors::ws::start.

earthskyorg commented 1 month ago
use actix_web::{web, App, HttpResponse};
use actix_web_actors::ws;
use futures_util::prelude::*;
use std::convert::TryInto;

async fn ws_handler(req: web::Path<(u32, u32)>, stream: web::Payload) -> impl IntoResponse {
    ws::start(req.into_inner(), &stream).await
}

#[actix_rt::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/ws/{id}/{room}", web::get().to(ws_handler))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}