use std::time::Duration;
use std::sync::{Arc, PoisonError};
use tokio::sync::RwLock;
use tokio::{io::{AsyncReadExt, AsyncWriteExt}, net::{TcpListener, TcpStream}, time::timeout, sync::MutexGuard};
use crate::http::router::Router;
use crate::http::middleware::Middlewares;
use crate::http::response::{Response, ResponseBytes, PotentialResponse};
use crate::http::request::{Request, RequestBuffer};
use crate::http::handler::Handler;
pub async fn connect_socket(listener: &TcpListener, router: Arc<Router>) {
let socket_result = listener.accept().await;
if socket_result.is_err() {
return;
}
let socket_result = socket_result.unwrap();
let (socket, _addr) = socket_result;
tokio::spawn(async move {
let (socket, response) = handle_connection(socket, router).await;
let response_bytes: ResponseBytes = response.to_bytes();
let (mut socket, err_response) = write_socket(socket, &response_bytes).await;
if err_response.is_some() {
}
let shutdown_result = socket.shutdown().await;
if shutdown_result.is_err() {
}
return;
});
}
pub async fn handle_connection(socket: TcpStream, router: Arc<Router>) -> (TcpStream, Response) {
let (socket, request_bytes, potetial_response) = read_socket(socket).await;
if potetial_response.is_some() {
return (socket, potetial_response.unwrap());
}
if request_bytes.len() == 0 {
return (socket, Response::new().status(200));
}
let (request, potential_response) = Request::new_from_bytes(request_bytes);
if potential_response.is_some() {
return (socket, potential_response.unwrap());
}
let response: Response = handle_request(router, request).await;
return (socket, response);
}
pub async fn handle_request(router: Arc<Router>, request: Request) -> Response {
let route_handler = router.routes.get(request.method_and_path.as_str());
if route_handler.is_none() {
return Response::new()
.status(404)
.body("route not found");
}
let route_handler = route_handler.unwrap();
let potential_route: Result<MutexGuard<(Handler, Middlewares, Middlewares)>, PoisonError<MutexGuard<(Handler, Middlewares, Middlewares)>>> = Ok(route_handler.lock().await); if potential_route.is_err() {
return Response::new()
.status(500)
.body("failed to lock route handler")
}
let route_handler = potential_route.unwrap();
let (handler, middlewares, outerwares) = &*route_handler;
let (request, potential_response) = handle_middleware(request, middlewares).await;
match potential_response {
Some(response) => {
return response;
},
None => {
let handler = handler.func.read().await;
let (request, handler_response) = handler(request).await;
let (_, potential_response) = handle_middleware(request, outerwares).await;
match potential_response {
Some(response) => {
return response;
},
None => {
return handler_response;
},
}
},
}
}
pub async fn handle_middleware(mut request: Request, middlewares: &Middlewares) -> (Request, PotentialResponse) {
if middlewares.len() == 0 {
return (request, None);
};
for middleware in middlewares {
let middleware = middleware.func.read().await;
let potential_response = middleware(&mut request).await;
if potential_response.is_none() {
continue;
}
let response = potential_response.unwrap();
return (request, Some(response));
}
return (request, None);
}
pub async fn read_socket(mut socket: TcpStream) -> (TcpStream, RequestBuffer, PotentialResponse) {
let mut buffer: [u8; 1024] = [0; 1024];
match timeout(Duration::from_secs(5), socket.read(&mut buffer)).await {
Ok(Ok(bytes_read)) if bytes_read > 0 => {
return (socket, buffer, None);
},
Ok(Ok(_)) => {
return (socket, buffer, Some(Response::new()
.status(500)
.body("no data received from client connection")
));
},
Ok(Err(e)) => {
return (socket, buffer, Some(Response::new()
.status(500)
.body(&format!("failed to read from socket: {}", e))
));
},
Err(_) => {
return (socket, buffer, Some(Response::new()
.status(408)
.body("read timeout")
));
},
}
}
pub async fn write_socket(mut socket: TcpStream, response_bytes: &[u8]) -> (TcpStream, PotentialResponse) {
match timeout(Duration::from_secs(5), socket.write_all(response_bytes)).await {
Ok(Ok(_)) => {
return (socket, None);
},
Ok(Err(e)) => {
return (socket, Some(Response::new()
.status(500)
.body(&format!("failed to write to socket: {}", e))
));
},
Err(_) => {
return (socket, Some(Response::new()
.status(408)
.body("write timeout")
));
},
}
}