From 52cd5aba8838b68a5afb857e78140a55962ce422 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 15 Jan 2022 02:15:21 -0800 Subject: [PATCH] gbg commit doesn't compile Signed-off-by: Erik Hollensbe --- Cargo.toml | 1 + src/handler.rs | 109 +++++++++++++++++++++++++++++++++++++++---------- src/lib.rs | 38 ++++++++++++++++- 3 files changed, 124 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1a1995b..ad2c92e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" hyper = { version = "*", features = [ "http1", "http2", "server", "runtime", "tcp", "stream" ] } http = "*" async-trait = "*" +tokio = { version = "*", features = [ "full" ] } diff --git a/src/handler.rs b/src/handler.rs index 03f09ed..90603af 100644 --- a/src/handler.rs +++ b/src/handler.rs @@ -1,50 +1,115 @@ -use crate::Params; +use std::sync::Arc; +use tokio::sync::Mutex; + +use crate::{HTTPResult, Params}; use async_trait::async_trait; -use hyper::{Error, Request, Response}; +use http::{Request, Response}; -pub type HandlerFunc = - dyn Fn(&Request, &Params, Option<&Response>) -> Result, Error>; +pub type HandlerFunc<'a, T, R> = + dyn Fn(&'a Request, Params, Option<&'a Response>) -> HTTPResult<'a, T, R>; #[async_trait] -pub trait Handler +pub trait Handler<'a, 'b, T, R> where - Self: Send + Sync + 'static, + Self: Send + Sync + 'b, { - async fn perform(&self, response: Option<&Response>) -> Result, Error>; + async fn perform(&'b self, response: Option<&'a Response>) -> HTTPResult<'a, T, R>; } -pub struct BasicHandler +pub struct BasicHandler<'a, T, R> where - T: Send + Sync + 'static, - R: Send + Sync + 'static, + T: Send + Sync + 'a, + R: Send + Sync + 'a, { - req: Request, + req: Arc>>, params: Params, - next: Option<&'static BasicHandler>, - func: &'static HandlerFunc, + next: Option<&'a BasicHandler<'a, T, R>>, + func: &'a HandlerFunc<'a, T, R>, } -impl BasicHandler +impl<'a, 'b, T, R> BasicHandler<'b, T, R> where - T: Send + Sync + 'static, - R: Send + Sync + 'static, + T: Send + Sync + 'b, + R: Send + Sync + 'b, { + pub fn new( + req: Request, + params: Params, + next: Option<&'b BasicHandler<'b, T, R>>, + func: &'static HandlerFunc<'b, T, R>, + ) -> Self { + Self { + req: Arc::new(Mutex::new(req)), + params, + next, + func, + } + } } #[async_trait] -impl Handler for BasicHandler +impl<'a, 'b, T, R> Handler<'a, 'b, T, R> for BasicHandler<'b, T, R> where - Self: Send + Sync, + Self: Send + Sync + 'b, R: Copy + Send + Sync + Sized + 'static, T: Copy + Send + Sync + Sized + 'static, { - async fn perform(&self, response: Option<&Response>) -> Result, Error> { - let response = (*self.func)(&self.req, &self.params, response)?; + async fn perform(&'b self, response: Option<&'a Response>) -> HTTPResult<'a, T, R> { + let mut req = self.req.lock().await; + + let (req, response) = (*self.func)(&mut req, self.params, response)?; if self.next.is_some() { - return Ok(self.next.unwrap().perform(Some(&response)).await?); + return Ok(self.next.unwrap().perform(response).await?); } - Ok(response) + Ok((req, response)) + } +} + +mod tests { + use crate::{Error, HTTPResult, Params}; + use http::{HeaderValue, Request, Response, StatusCode}; + use hyper::Body; + + fn one<'a>( + mut req: &'a Request, + _params: Params, + _response: Option<&'a Response>, + ) -> HTTPResult<'a, Body, Body> { + let headers = req.headers_mut(); + headers.insert("wakka", HeaderValue::from_str("wakka wakka").unwrap()); + Ok((&req, None)) + } + + fn two<'a>( + mut req: &'a Request, + _params: Params, + response: Option<&'a Response>, + ) -> HTTPResult<'a, Body, Body> { + if let Some(header) = req.headers().get("wakka") { + if header != "wakka wakka" { + return Err(Error::new("invalid header value")); + } + + if response.is_some() { + return Ok((&req, response)); + } else { + response.replace( + &Response::builder() + .status(StatusCode::OK) + .body(Body::default())?, + ); + + return Ok((&req, response)); + } + } + + Err(Error::default()) + } + + #[test] + fn test_handler_basic() { + let bh = super::BasicHandler::new(Request::default(), Params::default(), None, &one); } } diff --git a/src/lib.rs b/src/lib.rs index e4901b9..5c71049 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,7 @@ pub mod handler; +use http::{Request, Response}; + use crate::handler::BasicHandler; use std::collections::BTreeMap; @@ -7,7 +9,39 @@ use std::collections::BTreeMap; #[derive(Debug, Clone)] pub struct Params(BTreeMap); -pub struct App { +impl Default for Params { + fn default() -> Self { + Self(BTreeMap::default()) + } +} + +#[derive(Clone, Debug)] +pub struct Error(String); + +impl Default for Error { + fn default() -> Self { + Self(String::from("internal server error")) + } +} + +impl Error { + pub fn new(message: T) -> Self + where + T: ToString, + { + Self(message.to_string()) + } +} + +impl From for Error { + fn from(e: http::Error) -> Self { + Self::new(e) + } +} + +pub type HTTPResult<'a, Req, Resp> = Result<(&'a Request, Option<&'a Response>), Error>; + +pub struct App<'a> { #[allow(dead_code)] // FIXME remove - routes: BTreeMap>, + routes: BTreeMap>, }