mirror of
https://github.com/zerotier/ratpack.git
synced 2026-05-22 16:27:23 -07:00
fixed handlers!!!!one
Signed-off-by: Erik Hollensbe <linux@hollensbe.org>
This commit is contained in:
+1
-1
@@ -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" ] }
|
||||
|
||||
+34
-47
@@ -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<hyper::Body>, Option<Response<hyper::Body>>, Params) -> HTTPResult + Sync;
|
||||
|
||||
#[async_trait]
|
||||
pub trait Handler
|
||||
where
|
||||
Self: Sync + Sized,
|
||||
{
|
||||
async fn perform(
|
||||
&self,
|
||||
req: Request<hyper::Body>,
|
||||
response: Option<Response<hyper::Body>>,
|
||||
params: Params,
|
||||
) -> HTTPResult;
|
||||
}
|
||||
pub type HandlerFunc = fn(
|
||||
req: Request<Body>,
|
||||
response: Option<Response<Body>>,
|
||||
params: Params,
|
||||
) -> PinBox<dyn Future<Output = HTTPResult> + Send + 'static>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BasicHandler
|
||||
where
|
||||
Self: Sync + Sized,
|
||||
{
|
||||
next: Option<Arc<BasicHandler>>,
|
||||
func: &'static HandlerFunc,
|
||||
pub struct Handler {
|
||||
handler: HandlerFunc,
|
||||
next: Box<Option<Handler>>,
|
||||
}
|
||||
|
||||
impl BasicHandler
|
||||
impl Handler
|
||||
where
|
||||
Self: Sync + Sized,
|
||||
Self: Send + 'static,
|
||||
{
|
||||
pub fn new(next: Option<Arc<BasicHandler>>, func: &'static HandlerFunc) -> Self {
|
||||
Self { next, func }
|
||||
pub fn new(handler: HandlerFunc, next: Option<Handler>) -> 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<hyper::Body>,
|
||||
response: Option<Response<hyper::Body>>,
|
||||
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<Body>,
|
||||
_response: Option<Response<Body>>,
|
||||
_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<Body>,
|
||||
mut response: Option<Response<Body>>,
|
||||
_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)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -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<F> = Pin<Box<F>>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Error(String);
|
||||
@@ -36,5 +37,5 @@ pub type HTTPResult = Result<(Request<hyper::Body>, Option<Response<hyper::Body>
|
||||
|
||||
pub struct App {
|
||||
#[allow(dead_code)] // FIXME remove
|
||||
routes: BTreeMap<String, &'static BasicHandler>,
|
||||
routes: BTreeMap<String, Handler>,
|
||||
}
|
||||
|
||||
@@ -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<Params, Error> {
|
||||
let parts: Vec<&str> = provided.split("/").collect();
|
||||
let mut params = Params::default();
|
||||
|
||||
+8
-11
@@ -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<hyper::Body>) -> 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<hyper::Body>) -> Result<BasicHandler, Error> {
|
||||
pub fn find(&self, req: &'static Request<hyper::Body>) -> Result<Handler, Error> {
|
||||
let path = req.uri().path();
|
||||
|
||||
for route_path in self.0.clone() {
|
||||
|
||||
Reference in New Issue
Block a user