wsforge_core/router.rs
1//! Routing and server management for WebSocket connections with middleware support.
2//!
3//! This module provides the core routing infrastructure for WsForge, allowing you to
4//! define handlers for different message patterns, manage application state, add middleware
5//! layers, and configure server behavior. The router handles both WebSocket connections
6//! and static file serving on the same port.
7//!
8//! # Overview
9//!
10//! The [`Router`] is the main entry point for building a WebSocket server. It provides
11//! a builder-style API for:
12//! - Registering message handlers for specific routes
13//! - Adding global and per-route middleware layers
14//! - Managing shared application state
15//! - Serving static files (HTML, CSS, JS)
16//! - Configuring connection lifecycle callbacks
17//! - Managing WebSocket connections
18//!
19//! # Architecture
20//!
21//! ```
22//! ┌─────────────────┐
23//! │ TCP Listener │
24//! └────────┬────────┘
25//! │
26//! ├──→ HTTP Request → Static File Handler
27//! │
28//! └──→ WebSocket Upgrade → Connection Manager
29//! │
30//! ├──→ on_connect callback
31//! │
32//! ├──→ Global Middleware Chain
33//! │ ├──→ Middleware 1
34//! │ ├──→ Middleware 2
35//! │ └──→ Route-Specific Middleware
36//! │ └──→ Handler
37//! │
38//! └──→ on_disconnect callback
39//! ```
40//!
41//! # Middleware System
42//!
43//! WsForge supports a powerful middleware system with two types:
44//! - **Global middleware**: Applied to all routes
45//! - **Per-route middleware**: Applied only to specific routes
46//!
47//! Middleware execute in order: global first, then per-route, then the handler.
48//!
49//! # Examples
50//!
51//! ## Simple Echo Server
52//!
53//! ```
54//! use wsforge::prelude::*;
55//!
56//! async fn echo(msg: Message) -> Result<Message> {
57//! Ok(msg)
58//! }
59//!
60//! # async fn example() -> Result<()> {
61//! let router = Router::new()
62//! .default_handler(handler(echo));
63//!
64//! router.listen("127.0.0.1:8080").await?;
65//! # Ok(())
66//! # }
67//! ```
68//!
69//! ## With Global Middleware
70//!
71//! ```
72//! use wsforge::prelude::*;
73//!
74//! async fn echo(msg: Message) -> Result<Message> {
75//! Ok(msg)
76//! }
77//!
78//! # async fn example() -> Result<()> {
79//! let router = Router::new()
80//! .layer(LoggerMiddleware::new()) // Logs all messages
81//! .default_handler(handler(echo));
82//!
83//! router.listen("127.0.0.1:8080").await?;
84//! # Ok(())
85//! # }
86//! ```
87//!
88//! ## Multiple Routes with Per-Route Middleware
89//!
90//! ```
91//! use wsforge::prelude::*;
92//!
93//! async fn public_handler(msg: Message) -> Result<String> {
94//! Ok("Public response".to_string())
95//! }
96//!
97//! async fn admin_handler(msg: Message) -> Result<String> {
98//! Ok("Admin response".to_string())
99//! }
100//!
101//! # async fn example() -> Result<()> {
102//! # use std::sync::Arc;
103//! let router = Router::new()
104//! // Public route - no auth needed
105//! .route("/public", handler(public_handler))
106//!
107//! // Admin route - with auth middleware
108//! .route_with_layers(
109//! "/admin",
110//! vec![auth_middleware()],
111//! handler(admin_handler)
112//! );
113//!
114//! router.listen("127.0.0.1:8080").await?;
115//! # Ok(())
116//! # }
117//! # fn auth_middleware() -> Arc<dyn Middleware> { unimplemented!() }
118//! ```
119//!
120//! ## With State and Callbacks
121//!
122//! ```
123//! use wsforge::prelude::*;
124//! use std::sync::Arc;
125//!
126//! async fn broadcast(msg: Message, State(manager): State<Arc<ConnectionManager>>) -> Result<()> {
127//! manager.broadcast(msg);
128//! Ok(())
129//! }
130//!
131//! # async fn example() -> Result<()> {
132//! let router = Router::new()
133//! .layer(LoggerMiddleware::new())
134//! .default_handler(handler(broadcast))
135//! .on_connect(|manager, conn_id| {
136//! println!("✅ User {} connected (Total: {})", conn_id, manager.count());
137//! })
138//! .on_disconnect(|manager, conn_id| {
139//! println!("❌ User {} disconnected", conn_id);
140//! });
141//!
142//! router.listen("127.0.0.1:8080").await?;
143//! # Ok(())
144//! # }
145//! ```
146
147use crate::connection::{ConnectionId, ConnectionManager, handle_websocket};
148use crate::error::{Error, Result};
149use crate::extractor::Extensions;
150use crate::handler::Handler;
151use crate::message::Message;
152use crate::middleware::{Middleware, MiddlewareChain};
153use crate::state::AppState;
154use dashmap::DashMap;
155use std::net::SocketAddr;
156use std::path::PathBuf;
157use std::sync::Arc;
158use tokio::net::{TcpListener, TcpStream};
159use tokio_tungstenite::accept_async;
160use tracing::{error, info};
161
162/// Represents a single route with its path and middleware chain.
163///
164/// Routes map message patterns (paths) to handler functions with optional
165/// middleware layers. This is typically used internally by the [`Router`].
166///
167/// # Examples
168///
169/// ```
170/// use wsforge::prelude::*;
171///
172/// async fn my_handler() -> Result<String> {
173/// Ok("response".to_string())
174/// }
175///
176/// # fn example() {
177/// let mut chain = MiddlewareChain::new();
178/// chain.handler(handler(my_handler));
179///
180/// let route = Route {
181/// path: "/api/message".to_string(),
182/// chain: Arc::new(chain),
183/// };
184/// # }
185/// ```
186pub struct Route {
187 /// The route path (e.g., "/chat", "/api/users")
188 pub path: String,
189 /// The middleware chain and handler for this route
190 pub chain: Arc<MiddlewareChain>,
191}
192
193/// The main router for WebSocket servers with middleware support.
194///
195/// `Router` is the central component that manages routing, middleware, state, connections,
196/// and server lifecycle. It uses a builder pattern for configuration and supports both
197/// WebSocket and HTTP static file serving on the same port.
198///
199/// # Middleware System
200///
201/// The router supports two types of middleware:
202/// - **Global middleware** (added with [`layer()`](Self::layer)) - Applied to all routes
203/// - **Per-route middleware** (added with [`route_with_layers()`](Self::route_with_layers)) - Applied to specific routes
204///
205/// Execution order: Global middleware → Per-route middleware → Handler
206///
207/// # Thread Safety
208///
209/// Router is thread-safe and can be cloned cheaply (uses `Arc` internally).
210/// All connections share the same router instance.
211///
212/// # Examples
213///
214/// ## Basic Setup
215///
216/// ```
217/// use wsforge::prelude::*;
218///
219/// async fn handler(msg: Message) -> Result<String> {
220/// Ok("received".to_string())
221/// }
222///
223/// # async fn example() -> Result<()> {
224/// let router = Router::new()
225/// .default_handler(handler(handler));
226///
227/// router.listen("0.0.0.0:8080").await?;
228/// # Ok(())
229/// # }
230/// ```
231///
232/// ## With Middleware Layers
233///
234/// ```
235/// use wsforge::prelude::*;
236///
237/// # async fn handler(msg: Message) -> Result<String> { Ok("".to_string()) }
238/// # async fn example() -> Result<()> {
239/// let router = Router::new()
240/// .layer(LoggerMiddleware::new()) // Global: logs all
241/// .layer(auth_middleware()) // Global: auth all
242/// .route("/public", handler(handler)) // No extra middleware
243/// .route_with_layers(
244/// "/admin",
245/// vec![admin_only_middleware()], // Per-route: admin only
246/// handler(handler)
247/// );
248///
249/// router.listen("127.0.0.1:8080").await?;
250/// # Ok(())
251/// # }
252/// # fn auth_middleware() -> Arc<dyn Middleware> { unimplemented!() }
253/// # fn admin_only_middleware() -> Arc<dyn Middleware> { unimplemented!() }
254/// ```
255pub struct Router {
256 routes: Arc<DashMap<String, Arc<MiddlewareChain>>>,
257 global_middlewares: Vec<Arc<dyn Middleware>>,
258 state: AppState,
259 connection_manager: Arc<ConnectionManager>,
260 on_connect: Option<Arc<dyn Fn(&Arc<ConnectionManager>, ConnectionId) + Send + Sync>>,
261 on_disconnect: Option<Arc<dyn Fn(&Arc<ConnectionManager>, ConnectionId) + Send + Sync>>,
262 default_chain: Option<Arc<MiddlewareChain>>,
263 static_handler: Option<crate::static_files::StaticFileHandler>,
264}
265
266impl Router {
267 /// Creates a new empty router.
268 ///
269 /// The router starts with no routes, no middleware, no state, and no handlers.
270 /// Use the builder methods to configure it.
271 ///
272 /// # Examples
273 ///
274 /// ```
275 /// use wsforge::prelude::*;
276 ///
277 /// let router = Router::new();
278 /// ```
279 pub fn new() -> Self {
280 Self {
281 routes: Arc::new(DashMap::new()),
282 global_middlewares: Vec::new(),
283 state: AppState::new(),
284 connection_manager: Arc::new(ConnectionManager::new()),
285 on_connect: None,
286 on_disconnect: None,
287 default_chain: None,
288 static_handler: None,
289 }
290 }
291
292 /// Add a global middleware layer that applies to all routes.
293 ///
294 /// Global middleware are executed before per-route middleware and handlers.
295 /// They are executed in the order they are added.
296 ///
297 /// # Arguments
298 ///
299 /// * `middleware` - The middleware to add
300 ///
301 /// # Examples
302 ///
303 /// ## Single Middleware
304 ///
305 /// ```
306 /// use wsforge::prelude::*;
307 ///
308 /// # fn example() {
309 /// let router = Router::new()
310 /// .layer(LoggerMiddleware::new());
311 /// # }
312 /// ```
313 ///
314 /// ## Multiple Middleware
315 ///
316 /// ```
317 /// use wsforge::prelude::*;
318 ///
319 /// # fn example() {
320 /// let router = Router::new()
321 /// .layer(LoggerMiddleware::new()) // First: logging
322 /// .layer(auth_middleware()) // Second: authentication
323 /// .layer(rate_limit_middleware()); // Third: rate limiting
324 /// # }
325 /// # fn auth_middleware() -> Arc<dyn Middleware> { unimplemented!() }
326 /// # fn rate_limit_middleware() -> Arc<dyn Middleware> { unimplemented!() }
327 /// ```
328 pub fn layer(mut self, middleware: Arc<dyn Middleware>) -> Self {
329 self.global_middlewares.push(middleware);
330 self
331 }
332
333 /// Registers a handler for a specific route without additional middleware.
334 ///
335 /// Global middleware will still apply to this route. For route-specific middleware,
336 /// use [`route_with_layers()`](Self::route_with_layers).
337 ///
338 /// Routes are matched against the beginning of incoming messages.
339 /// For example, a message like `/chat hello` would match route `/chat`.
340 ///
341 /// # Arguments
342 ///
343 /// * `path` - The route path (e.g., "/chat", "/api/users")
344 /// * `handler` - The handler function wrapped with `handler()`
345 ///
346 /// # Examples
347 ///
348 /// ```
349 /// use wsforge::prelude::*;
350 ///
351 /// async fn chat_handler(msg: Message) -> Result<String> {
352 /// Ok("chat response".to_string())
353 /// }
354 ///
355 /// async fn api_handler(msg: Message) -> Result<String> {
356 /// Ok("api response".to_string())
357 /// }
358 ///
359 /// # fn example() {
360 /// let router = Router::new()
361 /// .route("/chat", handler(chat_handler))
362 /// .route("/api", handler(api_handler));
363 /// # }
364 /// ```
365 pub fn route(self, path: impl Into<String>, handler: Arc<dyn Handler>) -> Self {
366 let mut chain = MiddlewareChain::new();
367
368 // Add global middlewares first
369 for middleware in &self.global_middlewares {
370 chain = chain.layer(middleware.clone());
371 }
372
373 // Add handler
374 chain = chain.handler(handler);
375
376 self.routes.insert(path.into(), Arc::new(chain));
377 self
378 }
379
380 // Add a route with per-route middleware layers.
381 ///
382 /// Per-route middleware are executed after global middleware but before the handler.
383 /// This is useful for route-specific concerns like authorization or validation.
384 ///
385 /// # Arguments
386 ///
387 /// * `path` - The route path (e.g., "/admin", "/api/users")
388 /// * `layers` - Vector of middleware to apply to this route
389 /// * `handler` - The handler function wrapped with `handler()`
390 ///
391 /// # Examples
392 ///
393 /// ## Admin Route with Auth
394 ///
395 /// ```
396 /// use wsforge::prelude::*;
397 ///
398 /// async fn admin_handler(msg: Message) -> Result<String> {
399 /// Ok("Admin panel".to_string())
400 /// }
401 ///
402 /// # fn example() {
403 /// # use std::sync::Arc;
404 /// let router = Router::new()
405 /// .route_with_layers(
406 /// "/admin",
407 /// vec![
408 /// auth_middleware(),
409 /// admin_check_middleware(),
410 /// ],
411 /// handler(admin_handler)
412 /// );
413 /// # }
414 /// # fn auth_middleware() -> Arc<dyn Middleware> { unimplemented!() }
415 /// # fn admin_check_middleware() -> Arc<dyn Middleware> { unimplemented!() }
416 /// ```
417 ///
418 /// ## API Route with Validation
419 ///
420 /// ```
421 /// use wsforge::prelude::*;
422 ///
423 /// async fn api_handler(msg: Message) -> Result<String> {
424 /// Ok("API response".to_string())
425 /// }
426 ///
427 /// # fn example() {
428 /// # use std::sync::Arc;
429 /// let router = Router::new()
430 /// .route_with_layers(
431 /// "/api/users",
432 /// vec![validate_json_middleware()],
433 /// handler(api_handler)
434 /// );
435 /// # }
436 /// # fn validate_json_middleware() -> Arc<dyn Middleware> { unimplemented!() }
437 /// ```
438 pub fn route_with_layers(
439 self,
440 path: impl Into<String>,
441 layers: Vec<Arc<dyn Middleware>>,
442 handler: Arc<dyn Handler>,
443 ) -> Self {
444 let mut chain = MiddlewareChain::new();
445
446 // Add global middlewares first
447 for middleware in &self.global_middlewares {
448 chain = chain.layer(middleware.clone());
449 }
450
451 // Add route-specific middlewares
452 for middleware in layers {
453 chain = chain.layer(middleware);
454 }
455
456 // Add handler
457 chain = chain.handler(handler);
458
459 self.routes.insert(path.into(), Arc::new(chain));
460 self
461 }
462
463 /// Adds shared state to the router.
464 ///
465 /// State is shared across all connections and can be extracted in handlers
466 /// using the [`State`] extractor. Any type that is `Send + Sync + 'static`
467 /// can be used as state.
468 ///
469 /// # Type Safety
470 ///
471 /// Multiple different types can be added as state. Each type is stored
472 /// separately and retrieved by type.
473 ///
474 /// # Arguments
475 ///
476 /// * `data` - The state data to share (wrapped in `Arc`)
477 ///
478 /// # Examples
479 ///
480 /// ## Single State
481 ///
482 /// ```
483 /// use wsforge::prelude::*;
484 /// use std::sync::Arc;
485 ///
486 /// struct Database {
487 /// // database fields
488 /// }
489 ///
490 /// async fn handler(State(db): State<Arc<Database>>) -> Result<String> {
491 /// Ok("query result".to_string())
492 /// }
493 ///
494 /// # fn example() {
495 /// let db = Arc::new(Database {});
496 ///
497 /// let router = Router::new()
498 /// .with_state(db)
499 /// .default_handler(handler(handler));
500 /// # }
501 /// ```
502 ///
503 /// ## Multiple States
504 ///
505 /// ```
506 /// use wsforge::prelude::*;
507 /// use std::sync::Arc;
508 ///
509 /// struct Config {
510 /// port: u16,
511 /// }
512 ///
513 /// struct Database {
514 /// // database fields
515 /// }
516 ///
517 /// # fn example() {
518 /// let router = Router::new()
519 /// .with_state(Arc::new(Config { port: 8080 }))
520 /// .with_state(Arc::new(Database {}));
521 /// # }
522 /// ```
523 pub fn with_state<T: Send + Sync + 'static>(self, data: Arc<T>) -> Self {
524 self.state.insert(data);
525 self
526 }
527
528 /// Sets a callback to be called when a new connection is established.
529 ///
530 /// The callback receives a reference to the connection manager and the
531 /// connection ID. This is useful for logging, sending welcome messages,
532 /// or updating user lists.
533 ///
534 /// # Arguments
535 ///
536 /// * `f` - Callback function with signature `Fn(&Arc<ConnectionManager>, ConnectionId)`
537 ///
538 /// # Examples
539 ///
540 /// ## Simple Logging
541 ///
542 /// ```
543 /// use wsforge::prelude::*;
544 ///
545 /// # fn example() {
546 /// let router = Router::new()
547 /// .on_connect(|manager, conn_id| {
548 /// println!("New connection: {} (Total: {})", conn_id, manager.count());
549 /// });
550 /// # }
551 /// ```
552 ///
553 /// ## Send Welcome Message
554 ///
555 /// ```
556 /// use wsforge::prelude::*;
557 ///
558 /// # fn example() {
559 /// let router = Router::new()
560 /// .on_connect(|manager, conn_id| {
561 /// if let Some(conn) = manager.get(&conn_id) {
562 /// let _ = conn.send_text("Welcome to the server!");
563 /// }
564 /// });
565 /// # }
566 /// ```
567 ///
568 /// ## Broadcast Join Notification
569 ///
570 /// ```
571 /// use wsforge::prelude::*;
572 ///
573 /// # fn example() {
574 /// let router = Router::new()
575 /// .on_connect(|manager, conn_id| {
576 /// let msg = format!("User {} joined", conn_id);
577 /// manager.broadcast(Message::text(msg));
578 /// });
579 /// # }
580 /// ```
581 pub fn on_connect<F>(mut self, f: F) -> Self
582 where
583 F: Fn(&Arc<ConnectionManager>, ConnectionId) + Send + Sync + 'static,
584 {
585 self.on_connect = Some(Arc::new(f));
586 self
587 }
588
589 /// Sets a callback to be called when a connection is closed.
590 ///
591 /// The callback receives a reference to the connection manager and the
592 /// connection ID. Note that the connection is already removed from the
593 /// manager when this is called.
594 ///
595 /// # Arguments
596 ///
597 /// * `f` - Callback function with signature `Fn(&Arc<ConnectionManager>, ConnectionId)`
598 ///
599 /// # Examples
600 ///
601 /// ## Logging Disconnections
602 ///
603 /// ```
604 /// use wsforge::prelude::*;
605 ///
606 /// # fn example() {
607 /// let router = Router::new()
608 /// .on_disconnect(|manager, conn_id| {
609 /// println!("Connection {} closed (Remaining: {})", conn_id, manager.count());
610 /// });
611 /// # }
612 /// ```
613 ///
614 /// ## Broadcast Leave Notification
615 ///
616 /// ```
617 /// use wsforge::prelude::*;
618 ///
619 /// # fn example() {
620 /// let router = Router::new()
621 /// .on_disconnect(|manager, conn_id| {
622 /// let msg = format!("User {} left", conn_id);
623 /// manager.broadcast(Message::text(msg));
624 /// });
625 /// # }
626 /// ```
627 pub fn on_disconnect<F>(mut self, f: F) -> Self
628 where
629 F: Fn(&Arc<ConnectionManager>, ConnectionId) + Send + Sync + 'static,
630 {
631 self.on_disconnect = Some(Arc::new(f));
632 self
633 }
634
635 /// Sets the default handler for messages that don't match any route.
636 ///
637 /// This handler is called when no route matches the incoming message.
638 /// Global middleware will still be applied to the default handler.
639 ///
640 /// # Arguments
641 ///
642 /// * `handler` - The default handler wrapped with `handler()`
643 ///
644 /// # Examples
645 ///
646 /// ## Echo Server
647 ///
648 /// ```
649 /// use wsforge::prelude::*;
650 ///
651 /// async fn echo(msg: Message) -> Result<Message> {
652 /// Ok(msg)
653 /// }
654 ///
655 /// # fn example() {
656 /// let router = Router::new()
657 /// .default_handler(handler(echo));
658 /// # }
659 /// ```
660 ///
661 /// ## Error Handler
662 ///
663 /// ```
664 /// use wsforge::prelude::*;
665 ///
666 /// async fn not_found() -> Result<String> {
667 /// Ok("Unknown command".to_string())
668 /// }
669 ///
670 /// # fn example() {
671 /// let router = Router::new()
672 /// .route("/known", handler(not_found))
673 /// .default_handler(handler(not_found));
674 /// # }
675 /// ```
676 pub fn default_handler(mut self, handler: Arc<dyn Handler>) -> Self {
677 let mut chain = MiddlewareChain::new();
678
679 // Add global middlewares to default handler too
680 for middleware in &self.global_middlewares {
681 chain = chain.layer(middleware.clone());
682 }
683
684 chain = chain.handler(handler);
685 self.default_chain = Some(Arc::new(chain));
686 self
687 }
688
689 /// Enables static file serving from a directory.
690 ///
691 /// When enabled, the router will serve static files (HTML, CSS, JavaScript, images)
692 /// from the specified directory for HTTP requests, while still handling WebSocket
693 /// connections on the same port.
694 ///
695 /// # Path Resolution
696 ///
697 /// - Requests to `/` serve `index.html` from the directory
698 /// - Other requests map directly to files (e.g., `/style.css` → `directory/style.css`)
699 /// - MIME types are automatically detected
700 ///
701 /// # Security
702 ///
703 /// Path traversal attempts (e.g., `../../etc/passwd`) are automatically blocked.
704 ///
705 /// # Arguments
706 ///
707 /// * `path` - Path to the directory containing static files
708 ///
709 /// # Examples
710 ///
711 /// ## Serve Static Files
712 ///
713 /// ```
714 /// use wsforge::prelude::*;
715 ///
716 /// async fn ws_handler(msg: Message) -> Result<Message> {
717 /// Ok(msg)
718 /// }
719 ///
720 /// # fn example() {
721 /// let router = Router::new()
722 /// .serve_static("public") // Serve files from ./public
723 /// .default_handler(handler(ws_handler));
724 ///
725 /// // Now you can access:
726 /// // http://localhost:8080/ -> public/index.html
727 /// // http://localhost:8080/app.js -> public/app.js
728 /// // ws://localhost:8080 -> WebSocket handler
729 /// # }
730 /// ```
731 pub fn serve_static(mut self, path: impl Into<PathBuf>) -> Self {
732 self.static_handler = Some(crate::static_files::StaticFileHandler::new(path.into()));
733 self
734 }
735
736 /// Returns a reference to the connection manager.
737 ///
738 /// The connection manager is automatically created with the router.
739 /// Use this to get access to it for storing in state or elsewhere.
740 ///
741 /// # Examples
742 ///
743 /// ```
744 /// use wsforge::prelude::*;
745 ///
746 /// # fn example() {
747 /// let router = Router::new();
748 /// let manager = router.connection_manager();
749 ///
750 /// // Now you can use the manager
751 /// println!("Active connections: {}", manager.count());
752 /// # }
753 /// ```
754 pub fn connection_manager(&self) -> Arc<ConnectionManager> {
755 self.connection_manager.clone()
756 }
757
758 /// Starts the WebSocket server and listens for connections.
759 ///
760 /// This method consumes the router and starts the server loop. It will
761 /// run indefinitely until the process is terminated or an error occurs.
762 ///
763 /// The connection manager is automatically inserted into the router's state
764 /// before the server starts, making it available to all handlers via the
765 /// `State<Arc<ConnectionManager>>` extractor.
766 ///
767 /// # Arguments
768 ///
769 /// * `addr` - The address to bind to (e.g., "127.0.0.1:8080", "0.0.0.0:3000")
770 ///
771 /// # Errors
772 ///
773 /// Returns an error if:
774 /// - The address format is invalid
775 /// - The port is already in use
776 /// - Permission is denied (e.g., ports < 1024 on Unix)
777 ///
778 /// # Examples
779 ///
780 /// ## Basic Usage
781 ///
782 /// ```
783 /// use wsforge::prelude::*;
784 ///
785 /// # async fn example() -> Result<()> {
786 /// let router = Router::new();
787 /// router.listen("127.0.0.1:8080").await?;
788 /// # Ok(())
789 /// # }
790 /// ```
791 ///
792 /// ## All Interfaces
793 ///
794 /// ```
795 /// use wsforge::prelude::*;
796 ///
797 /// # async fn example() -> Result<()> {
798 /// let router = Router::new();
799 /// router.listen("0.0.0.0:8080").await?; // Accept connections from anywhere
800 /// # Ok(())
801 /// # }
802 /// ```
803 pub async fn listen(self, addr: impl AsRef<str>) -> Result<()> {
804 let addr: SocketAddr = addr
805 .as_ref()
806 .parse()
807 .map_err(|e| Error::custom(format!("Invalid address: {}", e)))?;
808
809 self.state.insert(self.connection_manager.clone());
810
811 let listener = TcpListener::bind(addr).await?;
812 info!("WebSocket server listening on {}", addr);
813
814 let router = Arc::new(self);
815
816 loop {
817 let (stream, peer_addr) = listener.accept().await?;
818 let router = router.clone();
819
820 tokio::spawn(async move {
821 if let Err(e) = router.handle_connection(stream, peer_addr).await {
822 error!("Connection error: {}", e);
823 }
824 });
825 }
826 }
827
828 async fn handle_connection(&self, stream: TcpStream, peer_addr: SocketAddr) -> Result<()> {
829 let mut buffer = [0u8; 1024];
830
831 let n = tokio::time::timeout(std::time::Duration::from_secs(5), stream.peek(&mut buffer))
832 .await
833 .map_err(|_| Error::custom("Connection timeout"))?
834 .map_err(|e| Error::custom(format!("Failed to read: {}", e)))?;
835
836 let header = String::from_utf8_lossy(&buffer[..n]);
837
838 if header.contains("Upgrade: websocket") || header.contains("upgrade: websocket") {
839 self.handle_websocket_connection(stream, peer_addr).await
840 } else if let Some(ref static_handler) = self.static_handler {
841 self.handle_http_request(stream, static_handler, &header)
842 .await
843 } else {
844 Err(Error::custom("No handler for HTTP requests"))
845 }
846 }
847
848 async fn handle_http_request(
849 &self,
850 mut stream: TcpStream,
851 static_handler: &crate::static_files::StaticFileHandler,
852 header: &str,
853 ) -> Result<()> {
854 use crate::static_files::http_response;
855 use tokio::io::AsyncWriteExt;
856
857 let path = header
858 .lines()
859 .next()
860 .and_then(|line| {
861 let parts: Vec<&str> = line.split_whitespace().collect();
862 if parts.len() >= 2 && (parts[0] == "GET" || parts[0] == "HEAD") {
863 Some(parts[1])
864 } else {
865 None
866 }
867 })
868 .unwrap_or("/");
869
870 let response = match static_handler.serve(path).await {
871 Ok((content, mime_type)) => {
872 info!("Served: {} ({} bytes)", path, content.len());
873 http_response(200, &mime_type, content)
874 }
875 Err(e) => {
876 tracing::warn!("File not found: {} - {}", path, e);
877 let html = b"<html><body><h1>404 Not Found</h1></body></html>".to_vec();
878 http_response(404, "text/html", html)
879 }
880 };
881
882 stream.write_all(&response).await?;
883 stream.flush().await?;
884 Ok(())
885 }
886
887 async fn handle_websocket_connection(
888 &self,
889 stream: TcpStream,
890 peer_addr: SocketAddr,
891 ) -> Result<()> {
892 let ws_stream = accept_async(stream).await?;
893 let conn_id = Self::generate_connection_id();
894
895 let router = self.clone();
896 let manager = self.connection_manager.clone();
897
898 let on_message = Arc::new(move |conn_id: ConnectionId, message: Message| {
899 let router = router.clone();
900 tokio::spawn(async move {
901 if let Err(e) = router.handle_message(conn_id, message).await {
902 error!("Message handling error: {}", e);
903 }
904 });
905 });
906
907 let manager_ref = manager.clone();
908 let on_connect = self
909 .on_connect
910 .clone()
911 .map(move |cb| {
912 let manager = manager_ref.clone();
913 Arc::new(move |conn_id: ConnectionId| {
914 cb(&manager, conn_id);
915 }) as Arc<dyn Fn(ConnectionId) + Send + Sync>
916 })
917 .unwrap_or_else(|| {
918 Arc::new(|conn_id: ConnectionId| {
919 info!("Client connected: {}", conn_id);
920 })
921 });
922
923 let manager_ref = manager.clone();
924 let on_disconnect = self
925 .on_disconnect
926 .clone()
927 .map(move |cb| {
928 let manager = manager_ref.clone();
929 Arc::new(move |conn_id: ConnectionId| {
930 cb(&manager, conn_id);
931 }) as Arc<dyn Fn(ConnectionId) + Send + Sync>
932 })
933 .unwrap_or_else(|| {
934 Arc::new(|conn_id: ConnectionId| {
935 info!("Client disconnected: {}", conn_id);
936 })
937 });
938
939 handle_websocket(
940 ws_stream,
941 conn_id,
942 peer_addr,
943 manager,
944 on_message,
945 on_connect,
946 on_disconnect,
947 )
948 .await;
949
950 Ok(())
951 }
952
953 async fn handle_message(&self, conn_id: ConnectionId, message: Message) -> Result<()> {
954 let conn = self
955 .connection_manager
956 .get(&conn_id)
957 .ok_or_else(|| Error::ConnectionNotFound(conn_id.clone()))?;
958
959 let extensions = Extensions::new();
960
961 let chain = if let Some(text) = message.as_text() {
962 if text.starts_with('/') {
963 if let Some((route, _)) = text.split_once(' ') {
964 self.routes.get(route).map(|c| c.value().clone())
965 } else {
966 self.routes.get(text).map(|c| c.value().clone())
967 }
968 } else {
969 None
970 }
971 } else {
972 None
973 };
974
975 let chain = chain.or_else(|| self.default_chain.clone());
976
977 if let Some(chain) = chain {
978 match chain
979 .execute(message, conn.clone(), self.state.clone(), extensions)
980 .await
981 {
982 Ok(Some(response)) => {
983 if let Err(e) = conn.send(response) {
984 error!("Failed to send response to {}: {}", conn_id, e);
985 }
986 }
987 Ok(None) => {
988 tracing::debug!("Handler processed message without response");
989 }
990 Err(e) => {
991 error!("Handler error for {}: {}", conn_id, e);
992 }
993 }
994 } else {
995 tracing::warn!("No handler found for message from {}", conn_id);
996 }
997
998 Ok(())
999 }
1000
1001 fn generate_connection_id() -> ConnectionId {
1002 use std::sync::atomic::{AtomicU64, Ordering};
1003 static COUNTER: AtomicU64 = AtomicU64::new(0);
1004 format!("conn_{}", COUNTER.fetch_add(1, Ordering::SeqCst))
1005 }
1006}
1007
1008impl Clone for Router {
1009 fn clone(&self) -> Self {
1010 Self {
1011 routes: self.routes.clone(),
1012 global_middlewares: self.global_middlewares.clone(),
1013 state: self.state.clone(),
1014 connection_manager: self.connection_manager.clone(),
1015 on_connect: self.on_connect.clone(),
1016 on_disconnect: self.on_disconnect.clone(),
1017 default_chain: self.default_chain.clone(),
1018 static_handler: self.static_handler.clone(),
1019 }
1020 }
1021}
1022
1023impl Default for Router {
1024 fn default() -> Self {
1025 Self::new()
1026 }
1027}