micro_web/
server.rs

1//! Server module for handling HTTP requests and managing web server lifecycle.
2//!
3//! This module provides the core server functionality including:
4//! - Server builder pattern for configuration
5//! - HTTP request routing and handling
6//! - Connection management and error handling
7//! - Default request handling
8//!
9//! # Examples
10//!
11//! ```no_run
12//! use micro_web::{Server, router::{Router, get}, handler_fn};
13//!
14//! async fn hello_world() -> &'static str {
15//!     "Hello, World!"
16//! }
17//!
18//! #[tokio::main]
19//! async fn main() {
20//!     let router = Router::builder()
21//!         .route("/", get(handler_fn(hello_world)))
22//!         .build();
23//!         
24//!     Server::builder()
25//!         .router(router)
26//!         .bind("127.0.0.1:3000")
27//!         .build()
28//!         .unwrap()
29//!         .start()
30//!         .await;
31//! }
32//! ```
33
34use crate::handler::RequestHandler;
35use crate::router::Router;
36use crate::{handler_fn, OptionReqBody, RequestContext, ResponseBody};
37use http::{Request, Response, StatusCode};
38use micro_http::connection::HttpConnection;
39use micro_http::handler::Handler;
40use micro_http::protocol::body::ReqBody;
41use micro_http::protocol::RequestHeader;
42use std::error::Error;
43use std::net::{SocketAddr, ToSocketAddrs};
44use std::sync::Arc;
45use thiserror::Error;
46use tokio::net::TcpListener;
47use tracing::{error, info, warn, Level};
48use tracing_subscriber::FmtSubscriber;
49
50/// Builder for configuring and constructing a [`Server`] instance.
51///
52/// The builder provides a fluent API for setting server options including:
53/// - Binding address
54/// - Request router
55/// - Default request handler
56pub struct ServerBuilder {
57    router: Option<Router>,
58    default_handler: Option<Box<dyn RequestHandler>>,
59    address: Option<Vec<SocketAddr>>,
60}
61
62impl ServerBuilder {
63    fn new() -> Self {
64        Self { router: None, default_handler: None, address: None }
65    }
66
67    pub fn bind<A: ToSocketAddrs>(mut self, address: A) -> Self {
68        self.address = Some(address.to_socket_addrs().unwrap().collect::<Vec<_>>());
69        self
70    }
71
72    pub fn router(mut self, router: Router) -> Self {
73        self.router = Some(router);
74        self
75    }
76
77    pub fn default_handler(mut self, request_handler: impl RequestHandler + 'static) -> Self {
78        self.default_handler = Some(Box::new(request_handler));
79        self
80    }
81
82    pub fn build(self) -> Result<Server, ServerBuildError> {
83        let new_builder = if self.default_handler.is_none() { self.default_handler(handler_fn(default_handler)) } else { self };
84        let router = new_builder.router.ok_or(ServerBuildError::MissingRouter)?;
85        let address = new_builder.address.ok_or(ServerBuildError::MissingAddress)?;
86
87        // unwrap is safe here because we set it in the new_builder
88        Ok(Server { router, default_handler: new_builder.default_handler.unwrap(), address })
89    }
90}
91
92async fn default_handler() -> (StatusCode, &'static str) {
93    (StatusCode::NOT_FOUND, "404 Not Found")
94}
95
96/// Core server implementation that processes HTTP requests.
97///
98/// The server is responsible for:
99/// - Listening for incoming connections
100/// - Routing requests to appropriate handlers
101/// - Managing connection lifecycle
102/// - Error handling and logging
103///
104pub struct Server {
105    router: Router,
106    default_handler: Box<dyn RequestHandler>,
107    address: Vec<SocketAddr>,
108}
109
110/// Errors that can occur during server construction.
111#[derive(Error, Debug)]
112pub enum ServerBuildError {
113    /// Router was not configured
114    #[error("router must be set")]
115    MissingRouter,
116
117    /// Bind address was not configured
118    #[error("address must be set")]
119    MissingAddress,
120}
121
122impl Server {
123    pub fn builder() -> ServerBuilder {
124        ServerBuilder::new()
125    }
126
127    pub async fn start(self) {
128        let subscriber = FmtSubscriber::builder().with_max_level(Level::WARN).finish();
129        tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed");
130
131        info!("start listening at {:?}", self.address);
132        let tcp_listener = match TcpListener::bind(self.address.as_slice()).await {
133            Ok(tcp_listener) => tcp_listener,
134            Err(e) => {
135                error!(cause = %e, "bind server error");
136                return;
137            }
138        };
139
140        let handler = Arc::new(self);
141        loop {
142            let (tcp_stream, _remote_addr) = match tcp_listener.accept().await {
143                Ok(stream_and_addr) => stream_and_addr,
144                Err(e) => {
145                    warn!(cause = %e, "failed to accept");
146                    continue;
147                }
148            };
149
150            let handler = handler.clone();
151
152            tokio::spawn(async move {
153                let (reader, writer) = tcp_stream.into_split();
154                let connection = HttpConnection::new(reader, writer);
155                match connection.process(handler).await {
156                    Ok(_) => {
157                        info!("finished process, connection shutdown");
158                    }
159                    Err(e) => {
160                        error!("service has error, cause {}, connection shutdown", e);
161                    }
162                }
163            });
164        }
165    }
166}
167
168impl Handler for Server {
169    type RespBody = ResponseBody;
170    type Error = Box<dyn Error + Send + Sync>;
171
172    async fn call(&self, req: Request<ReqBody>) -> Result<Response<Self::RespBody>, Self::Error> {
173        let (parts, body) = req.into_parts();
174        let header = RequestHeader::from(parts);
175        let req_body = OptionReqBody::from(body);
176
177        let path = header.uri().path();
178        let route_result = self.router.at(path);
179
180        let mut request_context = RequestContext::new(&header, route_result.params());
181
182        let handler = route_result
183            .router_items()
184            .iter()
185            .filter(|item| item.filter().matches(&request_context))
186            .map(|item| item.handler())
187            .take(1)
188            .next()
189            .unwrap_or(self.default_handler.as_ref());
190
191        let response = handler.invoke(&mut request_context, req_body).await;
192        Ok(response)
193    }
194}