use bytes::Bytes; use http_body_util::Full; use hyper::server::conn::http1; use hyper::service::Service; use hyper::{body::Incoming as IncomingBody, Request, Response}; use tokio::net::TcpListener; use std::future::Future; use std::net::SocketAddr; use std::pin::Pin; use std::sync::{Arc, Mutex}; #[path = "../benches/support/mod.rs"] mod support; use support::TokioIo; type Counter = i32; #[tokio::main] async fn main() -> Result<(), Box> { let addr: SocketAddr = ([127, 0, 0, 1], 3000).into(); let listener = TcpListener::bind(addr).await?; println!("Listening on http://{}", addr); let svc = Svc { counter: Arc::new(Mutex::new(0)), }; loop { let (stream, _) = listener.accept().await?; let io = TokioIo::new(stream); let svc_clone = svc.clone(); tokio::task::spawn(async move { if let Err(err) = http1::Builder::new().serve_connection(io, svc_clone).await { println!("Failed to serve connection: {:?}", err); } }); } } #[derive(Debug, Clone)] struct Svc { counter: Arc>, } impl Service> for Svc { type Response = Response>; type Error = hyper::Error; type Future = Pin> + Send>>; fn call(&self, req: Request) -> Self::Future { fn mk_response(s: String) -> Result>, hyper::Error> { Ok(Response::new(Full::new(Bytes::from(s)))) } if req.uri().path() != "/favicon.ico" { *self.counter.lock().expect("lock poisoned") += 1; } let res = match req.uri().path() { "/" => mk_response(format!("home! counter = {:?}", self.counter)), "/posts" => mk_response(format!("posts, of course! counter = {:?}", self.counter)), "/authors" => mk_response(format!( "authors extraordinare! counter = {:?}", self.counter )), _ => mk_response("oh no! not found".into()), }; Box::pin(async { res }) } }