From 53f3b4a26ed0e83842807c0fa530166b7d8b516f Mon Sep 17 00:00:00 2001 From: totodore Date: Fri, 25 Sep 2026 21:59:02 +0200 Subject: [PATCH 1/2] feat(socketio/svc): impl ws creation svc --- crates/socketioxide/src/service.rs | 38 ++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/crates/socketioxide/src/service.rs b/crates/socketioxide/src/service.rs index 55ea5225..03643f37 100644 --- a/crates/socketioxide/src/service.rs +++ b/crates/socketioxide/src/service.rs @@ -64,6 +64,28 @@ where } } +type WsReq = (St, http::Request<()>); + +/// Service to create a websocket connection +impl TowerSvc<(St, http::Request<()>)> for SocketIoService +where + A: Adapter, + S: Clone, + St: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send + 'static, +{ + type Response = , S> as HyperSvc>>::Response; + type Error = , S> as HyperSvc>>::Error; + type Future = , S> as HyperSvc>>::Future; + + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { + TowerSvc::>::poll_ready(&mut self.engine_svc, cx) + } + + fn call(&mut self, req: WsReq) -> Self::Future { + TowerSvc::>::call(&mut self.engine_svc, req) + } +} + /// Hyper 1.0 Service implementation. impl HyperSvc> for SocketIoService where @@ -84,6 +106,22 @@ where } } +/// Service to create a websocket connection +impl HyperSvc> for SocketIoService +where + S: Clone, + A: Adapter, + St: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send + 'static, +{ + type Response = , S> as HyperSvc>>::Response; + type Error = , S> as HyperSvc>>::Error; + type Future = , S> as HyperSvc>>::Future; + + fn call(&self, req: WsReq) -> Self::Future { + HyperSvc::>::call(&self.engine_svc, req) + } +} + impl SocketIoService { /// Creates a MakeService which can be used as a hyper service #[inline(always)] From f86221840db3cb306744fcd9310a7b3ec2b182e2 Mon Sep 17 00:00:00 2001 From: totodore Date: Sun, 27 Sep 2026 20:25:17 +0200 Subject: [PATCH 2/2] feat(engineio/ws): add ws init service --- crates/engineioxide/src/service/mod.rs | 51 +++++++++++++++++++++++ crates/engineioxide/src/service/parser.rs | 2 +- crates/socketioxide/src/service.rs | 9 ++-- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/crates/engineioxide/src/service/mod.rs b/crates/engineioxide/src/service/mod.rs index 6b9d1c13..e5f1adf0 100644 --- a/crates/engineioxide/src/service/mod.rs +++ b/crates/engineioxide/src/service/mod.rs @@ -44,6 +44,7 @@ use tower_service::Service as TowerSvc; use crate::{ body::ResponseBody, config::EngineIoConfig, engine::EngineIo, handler::EngineIoHandler, + service::parser::RequestInfo, }; mod futures; @@ -136,6 +137,24 @@ where } } +impl TowerSvc<(St, http::Request<()>)> for EngineIoService +where + H: EngineIoHandler, + St: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send + 'static, +{ + type Response = (); + type Error = parser::ParseError; + type Future = std::future::Ready>; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, (conn, req): (St, http::Request<()>)) -> Self::Future { + std::future::ready(ws_conn_inner(self.engine.clone(), conn, req)) + } +} + /// Hyper 1.0 Service implementation. impl HyperSvc> for EngineIoService where @@ -160,6 +179,38 @@ where } } +impl HyperSvc<(St, http::Request<()>)> for EngineIoService +where + H: EngineIoHandler, + St: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send + 'static, +{ + type Response = (); + type Error = parser::ParseError; + type Future = std::future::Ready>; + + fn call(&self, (conn, req): (St, http::Request<()>)) -> Self::Future { + std::future::ready(ws_conn_inner(self.engine.clone(), conn, req)) + } +} + +fn ws_conn_inner( + engine: Arc>, + conn: St, + req: http::Request<()>, +) -> Result<(), parser::ParseError> +where + H: EngineIoHandler, + St: tokio::io::AsyncRead + tokio::io::AsyncWrite + Unpin + Send + 'static, +{ + let RequestInfo { protocol, sid, .. } = RequestInfo::parse(&req, &engine.config)?; + + let (parts, _) = req.into_parts(); + let fut = crate::transport::ws::on_init(engine, conn, protocol, sid, parts); + tokio::spawn(fut); + + Ok(()) +} + #[cfg(feature = "__test_harness")] #[doc(hidden)] impl EngineIoService diff --git a/crates/engineioxide/src/service/parser.rs b/crates/engineioxide/src/service/parser.rs index 2cb5623a..2530dc27 100644 --- a/crates/engineioxide/src/service/parser.rs +++ b/crates/engineioxide/src/service/parser.rs @@ -127,7 +127,7 @@ pub struct RequestInfo { impl RequestInfo { /// Parse the request URI to extract the [`TransportType`](crate::service::TransportType) and the socket id. - fn parse(req: &Request, config: &EngineIoConfig) -> Result { + pub(crate) fn parse(req: &Request, config: &EngineIoConfig) -> Result { use ParseError::*; let query = req.uri().query().ok_or(UnknownTransport)?; diff --git a/crates/socketioxide/src/service.rs b/crates/socketioxide/src/service.rs index 03643f37..131ee613 100644 --- a/crates/socketioxide/src/service.rs +++ b/crates/socketioxide/src/service.rs @@ -54,13 +54,12 @@ where type Error = , S> as TowerSvc>>::Error; type Future = , S> as TowerSvc>>::Future; - #[inline(always)] fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { - self.engine_svc.poll_ready(cx) + TowerSvc::>::poll_ready(&mut self.engine_svc, cx) } - #[inline(always)] + fn call(&mut self, req: Request) -> Self::Future { - self.engine_svc.call(req) + TowerSvc::>::call(&mut self.engine_svc, req) } } @@ -102,7 +101,7 @@ where #[inline(always)] fn call(&self, req: Request) -> Self::Future { - self.engine_svc.call(req) + HyperSvc::>::call(&self.engine_svc, req) } }