aerosocket_server/
handler.rs

1//! WebSocket connection handlers
2//!
3//! This module provides handler abstractions for processing WebSocket connections.
4
5use aerosocket_core::{Message, Result};
6use std::pin::Pin;
7use std::future::Future;
8
9/// Trait for handling WebSocket connections
10pub trait Handler: Send + Sync + 'static {
11    /// Handle a new connection
12    fn handle<'a>(&'a self, connection: crate::connection::ConnectionHandle) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>>;
13    
14    /// Clone the handler
15    fn clone_box(&self) -> Box<dyn Handler>;
16}
17
18impl Clone for Box<dyn Handler> {
19    fn clone(&self) -> Box<dyn Handler> {
20        self.clone_box()
21    }
22}
23
24/// Boxed handler type
25pub type BoxedHandler = Box<dyn Handler>;
26
27/// Default handler implementation
28#[derive(Debug, Clone)]
29pub struct DefaultHandler;
30
31impl DefaultHandler {
32    /// Create a new default handler
33    pub fn new() -> Self {
34        Self
35    }
36}
37
38impl Default for DefaultHandler {
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl Handler for DefaultHandler {
45    fn handle<'a>(&'a self, connection: crate::connection::ConnectionHandle) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
46        Box::pin(async move {
47            // Get the connection from the handle
48            let mut conn = connection.try_lock().await
49                .map_err(|_| aerosocket_core::Error::Other("Failed to lock connection".to_string()))?;
50            
51            while let Some(msg) = conn.next().await? {
52                match msg {
53                    Message::Text(text) => {
54                        conn.send_text(text.as_str()).await?;
55                    }
56                    Message::Binary(data) => {
57                        conn.send_binary(data.as_bytes().to_vec()).await?;
58                    }
59                    Message::Ping(_) => {
60                        conn.pong(None).await?;
61                    }
62                    Message::Close(close_msg) => {
63                        let code = close_msg.code();
64                        let reason = close_msg.reason();
65                        conn.close(code, Some(reason)).await?;
66                        break;
67                    }
68                    Message::Pong(_) => {
69                        // Ignore pong messages
70                    }
71                }
72            }
73            
74            Ok(())
75        })
76    }
77    
78    fn clone_box(&self) -> Box<dyn Handler> {
79        Box::new(self.clone())
80    }
81}
82
83/// Echo handler implementation
84#[derive(Debug, Clone)]
85pub struct EchoHandler;
86
87impl EchoHandler {
88    /// Create a new echo handler
89    pub fn new() -> Self {
90        Self
91    }
92}
93
94impl Default for EchoHandler {
95    fn default() -> Self {
96        Self::new()
97    }
98}
99
100impl Handler for EchoHandler {
101    fn handle<'a>(&'a self, connection: crate::connection::ConnectionHandle) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
102        Box::pin(async move {
103            // Get the connection from the handle
104            let mut conn = connection.try_lock().await
105                .map_err(|_| aerosocket_core::Error::Other("Failed to lock connection".to_string()))?;
106            
107            while let Some(msg) = conn.next().await? {
108                match msg {
109                    Message::Text(text) => {
110                        let echo_text = format!("Echo: {}", text.as_str());
111                        conn.send_text(&echo_text).await?;
112                    }
113                    Message::Binary(data) => {
114                        conn.send_binary(data.as_bytes().to_vec()).await?;
115                    }
116                    Message::Ping(_) => {
117                        conn.pong(None).await?;
118                    }
119                    Message::Close(close_msg) => {
120                        let code = close_msg.code();
121                        let reason = close_msg.reason();
122                        conn.close(code, Some(reason)).await?;
123                        break;
124                    }
125                    Message::Pong(_) => {
126                        // Ignore pong messages
127                    }
128                }
129            }
130            
131            Ok(())
132        })
133    }
134    
135    fn clone_box(&self) -> Box<dyn Handler> {
136        Box::new(self.clone())
137    }
138}
139
140/// Function-based handler
141#[derive(Clone)]
142pub struct FnHandler<F> {
143    f: F,
144}
145
146impl<F> FnHandler<F> {
147    /// Create a new function-based handler
148    pub fn new(f: F) -> Self {
149        Self { f }
150    }
151}
152
153impl<F> Handler for FnHandler<F>
154where
155    F: Fn(crate::connection::ConnectionHandle) -> Pin<Box<dyn Future<Output = Result<()>> + Send>> + Send + Sync + Clone + 'static,
156{
157    fn handle<'a>(&'a self, connection: crate::connection::ConnectionHandle) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'a>> {
158        Box::pin((self.f)(connection))
159    }
160    
161    fn clone_box(&self) -> Box<dyn Handler> {
162        Box::new(self.clone())
163    }
164}
165
166impl<F> std::fmt::Debug for FnHandler<F> {
167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168        f.debug_struct("FnHandler")
169            .field("f", &"<function>")
170            .finish()
171    }
172}
173
174/// Create a handler from a function
175pub fn from_fn<F, Fut>(f: F) -> FnHandler<F>
176where
177    F: Fn(crate::connection::ConnectionHandle) -> Fut + Send + Sync + Clone + 'static,
178    Fut: Future<Output = Result<()>> + Send + 'static,
179{
180    FnHandler::new(f)
181}
182
183#[cfg(test)]
184mod tests {
185    use super::*;
186    use bytes::Bytes;
187
188    #[tokio::test]
189    async fn test_default_handler() {
190        let handler = DefaultHandler::new();
191        let remote = "127.0.0.1:12345".parse().unwrap();
192        let local = "127.0.0.1:8080".parse().unwrap();
193        let connection = crate::connection::Connection::new(remote, local);
194        
195        // Note: This test will fail until Connection::next and send are implemented
196        // For now, we just test that the handler can be created
197        assert!(true);
198    }
199
200    #[tokio::test]
201    async fn test_echo_handler() {
202        let handler = EchoHandler::new();
203        let remote = "127.0.0.1:12345".parse().unwrap();
204        let local = "127.0.0.1:8080".parse().unwrap();
205        let connection = crate::connection::Connection::new(remote, local);
206        
207        // Note: This test will fail until Connection::next and send are implemented
208        // For now, we just test that the handler can be created
209        assert!(true);
210    }
211
212    #[tokio::test]
213    async fn test_fn_handler() {
214        let handler = from_fn(|_conn| async {
215            Ok(())
216        });
217        
218        let remote = "127.0.0.1:12345".parse().unwrap();
219        let local = "127.0.0.1:8080".parse().unwrap();
220        let connection = crate::connection::Connection::new(remote, local);
221        
222        // Note: This test will fail until Connection::next and send are implemented
223        // For now, we just test that the handler can be created
224        assert!(true);
225    }
226}