1
2use std::convert::Infallible;
3use std::net::SocketAddr;
4
5use super::database::table_schema::SqlTableSchema;
6
7use super::api_http_server::routing::{Route, split_uri_args};
8use super::api_http_server::middleware::Middleware;
9use super::database::interfaces::DatabaseInterface;
10
11use hyper::{Body, Request, Response, StatusCode};
12
13
14pub struct App {
15 pub routes: Vec<Box<dyn Route + Send + Sync>>,
16 pub middleware: Vec<Box<dyn Middleware + Send + Sync>>,
17 pub database_interface: Box<dyn DatabaseInterface + Send + Sync>,
18}
19
20impl App {
21 fn match_route(&self, uri: String) -> Option<&SqlTableSchema> {
22 for route in &self.routes {
23 let route_match = route.matches_uri(uri.clone());
24 if route_match {
25 return Some(route.get_schema())
26 }
27 }
28 None
29 }
30
31 pub async fn handle_http_request(&self, req: Request<Body>, addr: SocketAddr) -> Result<Response<Body>, Infallible> {
32 if req.method() == hyper::Method::OPTIONS {
33 let response = Response::builder()
34 .header("Allow", "OPTIONS, GET, POST, DELETE, PATCH")
35 .header("Accept", "application/json")
36 .body(
37 Body::empty()
38 );
39 return Ok(response.unwrap())
40 }
41
42 let mut req = req;
43
44 log::info!("{} Request ({}) at {}", req.method(), addr, req.uri());
45
46 let (base_uri, _) = split_uri_args(req.uri().to_string());
47
48 let table_schema = self.match_route(base_uri);
49
50 for middleware in &self.middleware {
51 middleware.process_request(&mut req);
52 }
53
54 let response: Response<Body> = match table_schema {
55 None => {
56 Response::builder()
57 .status(StatusCode::NOT_FOUND)
58 .body(
59 Body::from("Route not found")
60 ).unwrap()
61 },
62 Some(table_schema) => {
63 self.database_interface.process_api_request(&mut req, table_schema).await
64 }
65 };
66 Ok(response)
67 }
68}