-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
48c1fec
commit 634e10b
Showing
16 changed files
with
480 additions
and
354 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
use crate::{response::IntoResponse, SharedAppState}; | ||
use http::{request::Parts, Request}; | ||
use hyper::body::Incoming; | ||
use std::convert::Infallible; | ||
|
||
pub mod path; | ||
|
||
pub type AppRequest = Request<Incoming>; | ||
|
||
mod private { | ||
#[derive(Debug, Clone, Copy)] | ||
pub enum ViaParts {} | ||
|
||
#[derive(Debug, Clone, Copy)] | ||
pub enum ViaRequest {} | ||
} | ||
|
||
pub trait FromRequestParts: Sized { | ||
type Rejection: IntoResponse; | ||
|
||
fn from_request_parts( | ||
parts: &mut Parts, | ||
state: &SharedAppState, | ||
) -> Result<Self, Self::Rejection>; | ||
} | ||
|
||
impl FromRequestParts for SharedAppState { | ||
type Rejection = Infallible; | ||
|
||
fn from_request_parts(_: &mut Parts, state: &SharedAppState) -> Result<Self, Self::Rejection> { | ||
Ok(state.clone()) | ||
} | ||
} | ||
|
||
pub trait FromRequest<M = private::ViaRequest>: Sized { | ||
type Rejection: IntoResponse; | ||
|
||
fn from_request(req: AppRequest, state: &SharedAppState) -> Result<Self, Self::Rejection>; | ||
} | ||
|
||
impl<T> FromRequest<private::ViaParts> for T | ||
where | ||
T: FromRequestParts, | ||
{ | ||
type Rejection = <Self as FromRequestParts>::Rejection; | ||
|
||
fn from_request(req: AppRequest, state: &SharedAppState) -> Result<Self, Self::Rejection> { | ||
let (mut parts, _) = req.into_parts(); | ||
Self::from_request_parts(&mut parts, state) | ||
} | ||
} | ||
|
||
impl FromRequest<()> for AppRequest { | ||
type Rejection = Infallible; | ||
|
||
fn from_request(req: AppRequest, _: &SharedAppState) -> Result<Self, Self::Rejection> { | ||
Ok(req) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
use super::FromRequestParts; | ||
use crate::SharedAppState; | ||
use http::request::Parts; | ||
use std::convert::Infallible; | ||
|
||
pub struct Path(pub String); | ||
|
||
impl FromRequestParts for Path { | ||
type Rejection = Infallible; | ||
|
||
fn from_request_parts(parts: &mut Parts, _: &SharedAppState) -> Result<Self, Self::Rejection> { | ||
Ok(Self(parts.uri.path().to_string())) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
use crate::{ | ||
extract::{AppRequest, FromRequest, FromRequestParts}, | ||
response::{AppResponse, IntoResponse}, | ||
SharedAppState, | ||
}; | ||
use std::{future::Future, pin::Pin}; | ||
|
||
pub trait Handler<T>: Clone + Send + Sized + 'static { | ||
type Future: Future<Output = AppResponse> + Send + 'static; | ||
|
||
fn call(self, req: AppRequest, state: SharedAppState) -> Self::Future; | ||
} | ||
|
||
impl<F, Fut, Res> Handler<()> for F | ||
where | ||
F: FnOnce() -> Fut + Clone + Send + 'static, | ||
Fut: Future<Output = Res> + Send, | ||
Res: IntoResponse, | ||
{ | ||
type Future = Pin<Box<dyn Future<Output = AppResponse> + Send>>; | ||
|
||
fn call(self, _: AppRequest, _: SharedAppState) -> Self::Future { | ||
Box::pin(async move { self().await.into_response() }) | ||
} | ||
} | ||
|
||
macro_rules! impl_handler { | ||
( | ||
[$($ty:ident),*], $last:ident | ||
) => { | ||
#[allow(non_snake_case, unused_mut)] | ||
impl<F, Fut, Res, M, $($ty,)* $last> Handler<(M, $($ty,)* $last,)> for F | ||
where | ||
F: FnOnce($($ty,)* $last,) -> Fut + Clone + Send + 'static, | ||
Fut: Future<Output = Res> + Send, | ||
Res: IntoResponse, | ||
$( $ty: FromRequestParts + Send, )* | ||
$( <$ty as FromRequestParts>::Rejection: IntoResponse, )* | ||
$last: FromRequest<M> + Send, | ||
<$last as FromRequest<M>>::Rejection: IntoResponse, | ||
{ | ||
type Future = Pin<Box<dyn Future<Output = AppResponse> + Send>>; | ||
|
||
fn call(self, req: AppRequest, state: SharedAppState) -> Self::Future { | ||
Box::pin(async move { | ||
let (mut parts, body) = req.into_parts(); | ||
let state = &state; | ||
|
||
$( | ||
let $ty = match $ty::from_request_parts(&mut parts, state) { | ||
Ok(value) => value, | ||
Err(rejection) => return rejection.into_response(), | ||
}; | ||
)* | ||
|
||
let req = AppRequest::from_parts(parts, body); | ||
|
||
let $last = match $last::from_request(req, state) { | ||
Ok(value) => value, | ||
Err(rejection) => return rejection.into_response(), | ||
}; | ||
|
||
let res = self($($ty,)* $last,).await; | ||
|
||
res.into_response() | ||
}) | ||
} | ||
} | ||
}; | ||
} | ||
|
||
#[rustfmt::skip] | ||
macro_rules! all_the_tuples { | ||
($name:ident) => { | ||
$name!([], T1); | ||
$name!([T1], T2); | ||
$name!([T1, T2], T3); | ||
$name!([T1, T2, T3], T4); | ||
$name!([T1, T2, T3, T4], T5); | ||
$name!([T1, T2, T3, T4, T5], T6); | ||
$name!([T1, T2, T3, T4, T5, T6], T7); | ||
$name!([T1, T2, T3, T4, T5, T6, T7], T8); | ||
$name!([T1, T2, T3, T4, T5, T6, T7, T8], T9); | ||
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9], T10); | ||
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10], T11); | ||
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11], T12); | ||
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12], T13); | ||
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13], T14); | ||
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14], T15); | ||
$name!([T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15], T16); | ||
}; | ||
} | ||
|
||
all_the_tuples!(impl_handler); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
use std::net::SocketAddr; | ||
use std::net::{IpAddr, Ipv4Addr, SocketAddr}; | ||
use tokio::net::TcpListener; | ||
use wayfind_hyper_example::start_server; | ||
|
||
#[tokio::main] | ||
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> { | ||
let addr: SocketAddr = "127.0.0.1:8000".parse()?; | ||
let listener = TcpListener::bind(addr).await?; | ||
let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8000); | ||
let listener = TcpListener::bind(&socket).await?; | ||
start_server(listener).await | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
use bytes::Bytes; | ||
use http::Response; | ||
use http_body_util::Full; | ||
use std::convert::Infallible; | ||
|
||
pub type AppResponse = Response<Full<Bytes>>; | ||
|
||
pub trait IntoResponse { | ||
fn into_response(self) -> AppResponse; | ||
} | ||
|
||
impl IntoResponse for AppResponse { | ||
fn into_response(self) -> AppResponse { | ||
self | ||
} | ||
} | ||
|
||
impl IntoResponse for Infallible { | ||
fn into_response(self) -> AppResponse { | ||
unreachable!() | ||
} | ||
} |
Oops, something went wrong.