use std::net::SocketAddr;
use std::sync::Arc;
use http_body_util::Full;
use hyper::body::{Bytes, Incoming};
use hyper::server::conn::http1;
use hyper::service::service_fn;
use hyper::{Error, Request, Response, StatusCode};
use hyper_util::rt::TokioIo;
use tokio::net::TcpListener;
use usher::capture::{find_capture, Captures};
use usher::http::HttpRouter;
use usher::prelude::*;
type Callee = Box<dyn Fn(Request<Incoming>, Captures) -> Response<Full<Bytes>> + Send + Sync>;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
let listener = TcpListener::bind(addr).await?;
let mut router: HttpRouter<Callee> =
HttpRouter::new(vec![Box::new(DynamicParser), Box::new(StaticParser)]);
router.get(
"/:name",
Box::new(|req, params| {
let path = req.uri().path();
let name = find_capture(path, ¶ms, "name").unwrap();
Response::new(format!("Hello, {}!\n", name).into())
}),
);
let router = Arc::new(router);
loop {
let (stream, _) = listener.accept().await?;
let io = TokioIo::new(stream);
let service = service_fn(|req: Request<Incoming>| {
let router = router.clone();
async move {
let method = req.method();
let path = req.uri().path();
let response = match router.handler(method, path) {
Some((handler, captures)) => handler(req, captures),
None => {
let mut response = Response::new(Full::new(Bytes::new()));
*response.status_mut() = StatusCode::NOT_FOUND;
response
}
};
Ok::<_, Error>(response)
}
});
if let Err(err) = http1::Builder::new().serve_connection(io, service).await {
println!("Error serving connection: {:?}", err);
}
}
}