1use std::convert::Infallible;
2use std::net::SocketAddr;
3use std::sync::Arc;
4use hyper::server::conn::http1;
5use hyper::service::service_fn;
6use hyper::{Request as HyperRequest, Response as HyperResponse};
7use hyper_util::rt::TokioIo;
8use tokio::net::TcpListener;
9use crate::{App, Request};
10
11pub async fn serve(
13 addr: SocketAddr,
14 app: App,
15) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
16 let app = Arc::new(app);
17 let listener = TcpListener::bind(addr).await?;
18
19 println!("🔥 Torch server listening on http://{}", addr);
20
21 loop {
22 let (stream, _) = listener.accept().await?;
23 let io = TokioIo::new(stream);
24 let app = app.clone();
25
26 tokio::task::spawn(async move {
27 let service = service_fn(move |req| {
28 let app = app.clone();
29 async move { handle_request(req, app).await }
30 });
31
32 if let Err(err) = http1::Builder::new().serve_connection(io, service).await {
33 eprintln!("Error serving connection: {:?}", err);
34 }
35 });
36 }
37}
38
39async fn handle_request(
41 hyper_req: HyperRequest<hyper::body::Incoming>,
42 app: Arc<App>,
43) -> Result<HyperResponse<http_body_util::Full<hyper::body::Bytes>>, Infallible> {
44 let (parts, body) = hyper_req.into_parts();
45
46 let request = match Request::from_hyper(parts, body).await {
48 Ok(req) => req,
49 Err(err) => {
50 eprintln!("Error parsing request: {:?}", err);
51 return Ok(create_error_response(500, "Internal Server Error"));
52 }
53 };
54
55 let response = app.handle_request(request).await;
57
58 Ok(response.into_hyper_response())
60}
61
62fn create_error_response(status: u16, message: &str) -> HyperResponse<http_body_util::Full<hyper::body::Bytes>> {
64 use http_body_util::Full;
65 use hyper::body::Bytes;
66
67 HyperResponse::builder()
68 .status(status)
69 .header("content-type", "text/plain")
70 .body(Full::new(Bytes::from(message.to_string())))
71 .unwrap()
72}
73
74#[derive(Debug, Clone)]
76pub struct ServerConfig {
77 pub max_connections: Option<usize>,
79 pub request_timeout: Option<u64>,
81 pub keep_alive_timeout: Option<u64>,
83 pub max_body_size: Option<usize>,
85}
86
87impl Default for ServerConfig {
88 fn default() -> Self {
89 Self {
90 max_connections: None,
91 request_timeout: Some(30),
92 keep_alive_timeout: Some(60),
93 max_body_size: Some(1024 * 1024), }
95 }
96}
97
98pub struct Server {
100 app: App,
101 config: ServerConfig,
102}
103
104impl Server {
105 pub fn new(app: App) -> Self {
107 Self {
108 app,
109 config: ServerConfig::default(),
110 }
111 }
112
113 pub fn config(mut self, config: ServerConfig) -> Self {
115 self.config = config;
116 self
117 }
118
119 pub fn max_connections(mut self, max: usize) -> Self {
121 self.config.max_connections = Some(max);
122 self
123 }
124
125 pub fn request_timeout(mut self, timeout_secs: u64) -> Self {
127 self.config.request_timeout = Some(timeout_secs);
128 self
129 }
130
131 pub fn keep_alive_timeout(mut self, timeout_secs: u64) -> Self {
133 self.config.keep_alive_timeout = Some(timeout_secs);
134 self
135 }
136
137 pub fn max_body_size(mut self, size: usize) -> Self {
139 self.config.max_body_size = Some(size);
140 self
141 }
142
143 pub async fn listen(
145 self,
146 addr: SocketAddr,
147 ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
148 serve(addr, self.app).await
149 }
150}
151
152#[cfg(test)]
153mod tests {
154 use super::*;
155 use crate::{App, Response};
156
157 #[test]
158 fn test_server_config() {
159 let config = ServerConfig::default();
160 assert_eq!(config.request_timeout, Some(30));
161 assert_eq!(config.keep_alive_timeout, Some(60));
162 assert_eq!(config.max_body_size, Some(1024 * 1024));
163 }
164
165 #[test]
166 fn test_server_builder() {
167 let app = App::new().get::<_, (crate::Request,)>("/", |_req: crate::Request| async { Response::ok() });
168
169 let _server = Server::new(app)
170 .max_connections(1000)
171 .request_timeout(60)
172 .keep_alive_timeout(120)
173 .max_body_size(2 * 1024 * 1024);
174 }
175}