use std::{ convert::Infallible, error::Error, path::PathBuf, sync::Arc, net::SocketAddr, }; use hyper::{ Body, Request, Response, Server, service::{ make_service_fn, service_fn, }, StatusCode, }; use ptth::{ http_serde::RequestParts, server::file_server, }; struct ServerState <'a> { handlebars: Arc >, } fn status_reply > (status: StatusCode, b: B) -> Response { Response::builder ().status (status).body (b.into ()).unwrap () } fn prefix_match <'a> (hay: &'a str, needle: &str) -> Option <&'a str> { if hay.starts_with (needle) { Some (&hay [needle.len ()..]) } else { None } } async fn handle_all (req: Request , state: Arc >) -> Result , Infallible> { let path = req.uri ().path (); //println! ("{}", path); if let Some (path) = prefix_match (path, "/files") { let root = PathBuf::from ("./"); let path = path.into (); let (parts, _) = req.into_parts (); let ptth_req = match RequestParts::from_hyper (parts.method, path, parts.headers) { Ok (x) => x, _ => return Ok (status_reply (StatusCode::BAD_REQUEST, "Bad request")), }; let ptth_resp = file_server::serve_all (state.handlebars.clone (), &root, ptth_req).await; let mut resp = Response::builder () .status (StatusCode::from (ptth_resp.parts.status_code)); use std::str::FromStr; for (k, v) in ptth_resp.parts.headers.into_iter () { resp = resp.header (hyper::header::HeaderName::from_str (&k).unwrap (), v); } let body = ptth_resp.body .map (|b| Body::wrap_stream (b)) .unwrap_or_else (|| Body::empty ()) ; let resp = resp.body (body).unwrap (); Ok (resp) } else { Ok (status_reply (StatusCode::NOT_FOUND, "404 Not Found\n")) } } #[tokio::main] async fn main () -> Result <(), Box > { let addr = SocketAddr::from(([0, 0, 0, 0], 4000)); let handlebars = Arc::new (file_server::load_templates ()?); let state = Arc::new (ServerState { handlebars, }); let make_svc = make_service_fn (|_conn| { let state = state.clone (); async { Ok::<_, Infallible> (service_fn (move |req| { let state = state.clone (); handle_all (req, state) })) } }); let server = Server::bind (&addr).serve (make_svc); server.await?; Ok (()) }