108 lines
2.2 KiB
Rust
108 lines
2.2 KiB
Rust
|
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,
|
||
|
prefix_match,
|
||
|
server::file_server,
|
||
|
};
|
||
|
|
||
|
struct ServerState <'a> {
|
||
|
handlebars: Arc <handlebars::Handlebars <'a>>,
|
||
|
}
|
||
|
|
||
|
fn status_reply <B: Into <Body>> (status: StatusCode, b: B)
|
||
|
-> Response <Body>
|
||
|
{
|
||
|
Response::builder ().status (status).body (b.into ()).unwrap ()
|
||
|
}
|
||
|
|
||
|
async fn handle_all (req: Request <Body>, state: Arc <ServerState <'static>>)
|
||
|
-> Result <Response <Body>, 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, &root, ptth_req.method, &ptth_req.uri, &ptth_req.headers).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 (Body::wrap_stream)
|
||
|
.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 <dyn Error>> {
|
||
|
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 (())
|
||
|
}
|