Skip to content

Commit

Permalink
chore(viz): implement Handler for Responder
Browse files Browse the repository at this point in the history
  • Loading branch information
fundon committed Dec 30, 2023
1 parent dab9bd7 commit cb27f98
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 43 deletions.
8 changes: 4 additions & 4 deletions examples/hello-world/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#![deny(warnings)]
#![allow(clippy::unused_async)]

use std::{net::SocketAddr, str::FromStr, sync::Arc};
use std::{net::SocketAddr, str::FromStr};
use tokio::net::TcpListener;
use viz::{serve, Request, Result, Router, Tree};

async fn index(_: Request) -> Result<&'static str> {
Ok("Hello, World!")
async fn index(_: Request) -> Result<String> {
Ok(String::from("Hello, World!"))
}

#[tokio::main]
Expand All @@ -21,7 +21,7 @@ async fn main() -> Result<()> {
app = app.get(&format!("/{}", n), index);
}

let tree = Arc::new(Tree::from(app));
let tree = Tree::from(app);

loop {
let (stream, addr) = listener.accept().await?;
Expand Down
2 changes: 1 addition & 1 deletion viz-router/src/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ impl Tree {
) -> Option<(&'a BoxHandler, Path<'a, 'b>)> {
self.0
.iter()
.find_map(|(m, t)| (m == method).then(|| t.find(path)).flatten())
.find_map(|(m, t)| if m == method { t.find(path) } else { None })
}

/// Consumes the Tree, returning the wrapped value.
Expand Down
65 changes: 34 additions & 31 deletions viz/src/responder.rs
Original file line number Diff line number Diff line change
@@ -1,64 +1,67 @@
use std::{convert::Infallible, future::Future, net::SocketAddr, pin::Pin, sync::Arc};
use std::{convert::Infallible, net::SocketAddr, sync::Arc};

use crate::{
types::RouteInfo, Body, Handler, Incoming, IntoResponse, Method, Request, Response, StatusCode,
Tree,
future::{FutureExt, TryFutureExt},
types::RouteInfo,
Body, BoxFuture, Handler, Incoming, IntoResponse, Method, Request, Response, StatusCode, Tree,
};

/// Handles the HTTP [`Request`] and retures the HTTP [`Response`].
#[derive(Debug)]
pub struct Responder {
tree: Arc<Tree>,
tree: Tree,
addr: Option<SocketAddr>,
}

impl Responder {
/// Creates a Responder for handling the [`Request`].
#[must_use]
pub fn new(tree: Arc<Tree>, addr: Option<SocketAddr>) -> Self {
pub fn new(tree: Tree, addr: Option<SocketAddr>) -> Self {
Self { tree, addr }
}
}

impl Handler<Request<Incoming>> for Responder {
type Output = Result<Response, Infallible>;

/// Serves a request and returns a response.
async fn serve(
mut req: Request<Incoming>,
tree: Arc<Tree>,
addr: Option<SocketAddr>,
) -> Result<Response, Infallible> {
fn call(&self, mut req: Request<Incoming>) -> BoxFuture<Self::Output> {
let method = req.method().clone();
let path = req.uri().path().to_owned();
let path = req.uri().path().to_string();

let Some((handler, route)) = tree.find(&method, &path).or_else(|| {
let matched = self.tree.find(&method, &path).or_else(|| {
if method == Method::HEAD {
tree.find(&Method::GET, &path)
self.tree.find(&Method::GET, &path)
} else {
None
}
}) else {
return Ok(StatusCode::NOT_FOUND.into_response());
};
});

if let Some((handler, route)) = matched {
req.extensions_mut().insert(self.addr);
req.extensions_mut().insert(Arc::from(RouteInfo {
id: *route.id,
pattern: route.pattern(),
params: route.params().into(),
}));

req.extensions_mut().insert(addr);
req.extensions_mut().insert(Arc::from(RouteInfo {
id: *route.id,
pattern: route.pattern(),
params: route.params().into(),
}));
// req.set_state(tree.clone());
Ok(handler
.call(req.map(Body::Incoming))
.await
.unwrap_or_else(IntoResponse::into_response))
Box::pin(
handler
.call(req.map(Body::Incoming))
.unwrap_or_else(IntoResponse::into_response)
.map(Result::Ok),
)
} else {
Box::pin(async { Ok(StatusCode::NOT_FOUND.into_response()) })
}
}
}

impl hyper::service::Service<Request<Incoming>> for Responder {
type Response = Response;
type Error = Infallible;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
type Future = BoxFuture<Result<Self::Response, Self::Error>>;

#[inline]
fn call(&self, req: Request<Incoming>) -> Self::Future {
Box::pin(Self::serve(req, self.tree.clone(), self.addr))
Handler::call(self, req)
}
}
10 changes: 3 additions & 7 deletions viz/src/serve.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{net::SocketAddr, sync::Arc};
use std::net::SocketAddr;

use hyper_util::{rt::TokioExecutor, server::conn::auto::Builder};
use tokio::io::{AsyncRead, AsyncWrite};
Expand All @@ -13,7 +13,7 @@ use crate::Responder;
/// # Errors
///
/// Will return `Err` if the connection does not be served.
pub async fn serve<I>(stream: I, tree: Arc<Tree>, addr: Option<SocketAddr>) -> Result<()>
pub async fn serve<I>(stream: I, tree: Tree, addr: Option<SocketAddr>) -> Result<()>
where
I: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
Expand All @@ -28,11 +28,7 @@ where
/// # Errors
///
/// Will return `Err` if the connection does not be served.
pub async fn serve_with_upgrades<I>(
stream: I,
tree: Arc<Tree>,
addr: Option<SocketAddr>,
) -> Result<()>
pub async fn serve_with_upgrades<I>(stream: I, tree: Tree, addr: Option<SocketAddr>) -> Result<()>
where
I: AsyncRead + AsyncWrite + Unpin + Send + 'static,
{
Expand Down

0 comments on commit cb27f98

Please sign in to comment.