From b841c8589d0ae212ff68b71a13ffcc3009a007ab Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Wed, 19 Jan 2022 12:26:15 -0800 Subject: [PATCH] fixed handlers!!!!one Signed-off-by: Erik Hollensbe --- Cargo.toml | 2 +- src/handler.rs | 81 +++++++++++++++++++++----------------------------- src/lib.rs | 7 +++-- src/path.rs | 2 ++ src/router.rs | 19 +++++------- 5 files changed, 49 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ad2c92e..92272fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,5 @@ edition = "2021" [dependencies] hyper = { version = "*", features = [ "http1", "http2", "server", "runtime", "tcp", "stream" ] } http = "*" -async-trait = "*" +async-recursion = "*" tokio = { version = "*", features = [ "full" ] } diff --git a/src/handler.rs b/src/handler.rs index 12a0151..71a9bd0 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -1,62 +1,46 @@ -use std::{collections::BTreeMap, sync::Arc}; +use std::{collections::BTreeMap, future::Future}; -use crate::HTTPResult; +use crate::{HTTPResult, PinBox}; +use async_recursion::async_recursion; -use async_trait::async_trait; use http::{Request, Response}; +use hyper::Body; pub(crate) type Params = BTreeMap<&'static str, &'static str>; -pub type HandlerFunc = - dyn Fn(Request, Option>, Params) -> HTTPResult + Sync; - -#[async_trait] -pub trait Handler -where - Self: Sync + Sized, -{ - async fn perform( - &self, - req: Request, - response: Option>, - params: Params, - ) -> HTTPResult; -} +pub type HandlerFunc = fn( + req: Request, + response: Option>, + params: Params, +) -> PinBox + Send + 'static>; #[derive(Clone)] -pub struct BasicHandler -where - Self: Sync + Sized, -{ - next: Option>, - func: &'static HandlerFunc, +pub struct Handler { + handler: HandlerFunc, + next: Box>, } -impl BasicHandler +impl Handler where - Self: Sync + Sized, + Self: Send + 'static, { - pub fn new(next: Option>, func: &'static HandlerFunc) -> Self { - Self { next, func } + pub fn new(handler: HandlerFunc, next: Option) -> Self { + Self { + handler, + next: Box::new(next), + } } -} -#[async_trait] -impl Handler for BasicHandler -where - Self: Sync + Sized, -{ - async fn perform( + #[async_recursion(?Send)] + pub async fn perform( &self, req: Request, response: Option>, params: Params, ) -> HTTPResult { - let (req, response) = (*self.func)(req, response, params.clone())?; + let (req, response) = (self.handler)(req, response, params.clone()).await?; if self.next.is_some() { - return Ok(self - .next - .clone() + return Ok((*self.clone().next) .unwrap() .perform(req, response, params) .await?); @@ -77,7 +61,7 @@ mod tests { // wakka: wakka wakka // to the request. that's it! #[allow(dead_code)] - fn one( + async fn one( mut req: Request, _response: Option>, _params: Params, @@ -89,7 +73,7 @@ mod tests { // this method returns an OK status when the wakka header exists. #[allow(dead_code)] - fn two( + async fn two( req: Request, mut response: Option>, _params: Params, @@ -117,11 +101,8 @@ mod tests { // orchestration!!!! #[tokio::test] async fn test_handler_basic() { - use super::Handler; - use std::sync::Arc; - // single stage handler that never yields a response - let bh = super::BasicHandler::new(None, &one); + let bh = super::Handler::new(|req, resp, params| Box::pin(one(req, resp, params)), None); let req = Request::default(); let (req, response) = bh.perform(req, None, Params::new()).await.unwrap(); if !req.headers().get("wakka").is_some() { @@ -133,8 +114,12 @@ mod tests { } // two-stage handler; yields a response if the first one was good. - let bh_two = super::BasicHandler::new(None, &two); - let bh = super::BasicHandler::new(Some(Arc::new(bh_two.clone())), &one); + let bh_two = + super::Handler::new(|req, resp, params| Box::pin(two(req, resp, params)), None); + let bh = super::Handler::new( + |req, resp, params| Box::pin(one(req, resp, params)), + Some(bh_two.clone()), + ); let (_, response) = bh.perform(req, None, Params::new()).await.unwrap(); if !(response.is_some() && response.unwrap().status() == StatusCode::OK) { @@ -148,5 +133,7 @@ mod tests { { panic!("no error") } + + drop(bh) } } diff --git a/src/lib.rs b/src/lib.rs index 0aaefc6..e341ee6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,11 +2,12 @@ pub mod handler; pub mod path; pub mod router; +use handler::Handler; use http::{Request, Response}; -use crate::handler::BasicHandler; +use std::{collections::BTreeMap, pin::Pin}; -use std::collections::BTreeMap; +pub(crate) type PinBox = Pin>; #[derive(Clone, Debug)] pub struct Error(String); @@ -36,5 +37,5 @@ pub type HTTPResult = Result<(Request, Option pub struct App { #[allow(dead_code)] // FIXME remove - routes: BTreeMap, + routes: BTreeMap, } diff --git a/src/path.rs b/src/path.rs index f8d37a6..cfb3795 100644 --- a/src/path.rs +++ b/src/path.rs @@ -47,6 +47,7 @@ impl Path { self.clone() } + #[allow(dead_code)] pub(crate) fn params(&self) -> Vec<&str> { let mut params = Vec::new(); for arg in self.0.clone() { @@ -59,6 +60,7 @@ impl Path { params } + #[allow(dead_code)] pub(crate) fn extract(&self, provided: &'static str) -> Result { let parts: Vec<&str> = provided.split("/").collect(); let mut params = Params::default(); diff --git a/src/router.rs b/src/router.rs index 59ae8c8..40e81c2 100644 --- a/src/router.rs +++ b/src/router.rs @@ -1,18 +1,14 @@ -use std::collections::{BTreeMap, BTreeSet, HashSet}; +use std::collections::BTreeSet; use http::Request; -use crate::{ - handler::{BasicHandler, Handler}, - path::Path, - Error, HTTPResult, -}; +use crate::{handler::Handler, path::Path, Error, HTTPResult}; #[derive(Clone)] pub struct Route { method: http::Method, path: Path, - handler: BasicHandler, + handler: Handler, } impl PartialEq for Route { @@ -41,7 +37,7 @@ impl Ord for Route { } impl Route { - fn new(method: http::Method, path: &'static str, handler: BasicHandler) -> Self { + fn new(method: http::Method, path: &'static str, handler: Handler) -> Self { Self { method, handler, @@ -49,6 +45,7 @@ impl Route { } } + #[allow(dead_code)] async fn dispatch(&self, provided: &'static str, req: Request) -> HTTPResult { let params = self.path.extract(provided)?; self.handler.perform(req, None, params).await @@ -63,12 +60,12 @@ impl Router { Self(BTreeSet::new()) } - pub fn add(&mut self, method: http::Method, path: &'static str, bh: BasicHandler) -> Self { - self.0.insert(Route::new(method, path, bh)); + pub fn add(&mut self, method: http::Method, path: &'static str, ch: Handler) -> Self { + self.0.insert(Route::new(method, path, ch)); self.clone() } - pub fn find(&self, req: &'static Request) -> Result { + pub fn find(&self, req: &'static Request) -> Result { let path = req.uri().path(); for route_path in self.0.clone() {