Skip to main content

rust_api/
server.rs

1//! Server runtime for RustAPI framework
2//!
3//! Provides the main `RustAPI` struct for configuring and running the HTTP
4//! server.
5
6use std::net::SocketAddr;
7
8use crate::{error::Result, router::Router};
9
10/// Main RustAPI server struct with builder pattern for configuration
11///
12/// # Example
13///
14/// ```ignore
15/// let app = Router::new().route("/", get(handler));
16///
17/// RustAPI::new(app)
18///     .port(8080)
19///     .serve()
20///     .await?;
21/// ```
22pub struct RustAPI {
23    router: Router,
24    port: u16,
25    host: String,
26}
27
28impl RustAPI {
29    /// Create a new RustAPI server with the given router
30    ///
31    /// Defaults to running on `0.0.0.0:3000`
32    pub fn new(router: Router) -> Self {
33        Self {
34            router,
35            port: 3000,
36            host: "0.0.0.0".to_string(),
37        }
38    }
39
40    /// Set the port to listen on (default: 3000)
41    pub fn port(mut self, port: u16) -> Self {
42        self.port = port;
43        self
44    }
45
46    /// Set the host to bind to (default: "0.0.0.0")
47    pub fn host(mut self, host: impl Into<String>) -> Self {
48        self.host = host.into();
49        self
50    }
51
52    /// Start the HTTP server
53    ///
54    /// This will bind to the configured host and port, and start serving
55    /// requests.
56    pub async fn serve(self) -> Result<()> {
57        let addr = format!("{}:{}", self.host, self.port);
58        let socket_addr: SocketAddr = addr.parse().map_err(|e| {
59            crate::error::Error::server_error(format!("Invalid address {}: {}", addr, e))
60        })?;
61
62        let listener = tokio::net::TcpListener::bind(socket_addr)
63            .await
64            .map_err(|e| {
65                crate::error::Error::server_error(format!(
66                    "Failed to bind to {}: {}",
67                    socket_addr, e
68                ))
69            })?;
70
71        tracing::info!("Server running on http://{}", socket_addr);
72
73        // Router is already Axum's router (type alias), serve it directly
74        axum::serve(listener, self.router)
75            .await
76            .map_err(|e| crate::error::Error::server_error(format!("Server error: {}", e)))
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83
84    #[test]
85    fn test_rust_api_defaults() {
86        let router = crate::router::build();
87        let server = RustAPI::new(router);
88        assert_eq!(server.port, 3000);
89        assert_eq!(server.host, "0.0.0.0");
90    }
91
92    #[test]
93    fn test_rust_api_builder() {
94        let router = crate::router::build();
95        let server = RustAPI::new(router).port(8080).host("127.0.0.1");
96        assert_eq!(server.port, 8080);
97        assert_eq!(server.host, "127.0.0.1");
98    }
99}