Skip to content

Commit

Permalink
feat(volo-http): optimize code by afit & rpitit
Browse files Browse the repository at this point in the history
  • Loading branch information
bobozhengsir committed Oct 25, 2023
1 parent 3124977 commit da44579
Show file tree
Hide file tree
Showing 11 changed files with 226 additions and 531 deletions.
224 changes: 41 additions & 183 deletions Cargo.lock

Large diffs are not rendered by default.

39 changes: 0 additions & 39 deletions examples/src/http/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,8 @@ use serde::{Deserialize, Serialize};
use volo_http::{
handler::HandlerService,
request::Json,
<<<<<<< HEAD
route::{Route, Router, Server, ServiceLayerExt},
<<<<<<< HEAD
=======
=======
use http::{Response, StatusCode};
=======
use http::{Method, Response, StatusCode, Uri};
>>>>>>> handler, extractor (#221)
use hyper::body::Incoming;
use motore::service::service_fn;
=======
>>>>>>> layer (#224)
use serde::{Deserialize, Serialize};
use volo_http::{
handler::HandlerService,
request::Json,
<<<<<<< HEAD
route::{Route, Router},
>>>>>>> init
=======
route::{Route, Router, Server, ServiceLayerExt},
>>>>>>> layer (#224)
=======
route::{Route, Router, ServiceLayerExt},
server::Server,
>>>>>>> add graceful shutdown
>>>>>>> de495fd... add graceful shutdown
HttpContext,
};

Expand Down Expand Up @@ -113,23 +87,10 @@ async fn main() {
.post(HandlerService::new(test))
.build(),
)
<<<<<<< HEAD
=======
<<<<<<< HEAD
<<<<<<< HEAD
>>>>>>> handler, extractor (#221)
=======
>>>>>>> de495fd... add graceful shutdown
.layer(TimeoutLayer::new(Some(std::time::Duration::from_secs(1))))
.serve(SocketAddr::from(([127, 0, 0, 1], 3000)))
.await
.unwrap();
=======
.layer(TimeoutLayer::new(Some(std::time::Duration::from_secs(1))));

let addr: SocketAddr = "[::]:9091".parse().unwrap();
let addr = volo::net::Address::from(addr);

Server::new(app).run(addr).await.unwrap();
>>>>>>> add graceful shutdown
}
16 changes: 2 additions & 14 deletions volo-http/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ categories = ["asynchronous", "network-programming", "web-programming"]
keywords = ["async", "http"]

[dependencies]
volo = { version = "0.5", path = "../volo" }
volo = { version = "0.8", path = "../volo" }
hyper = { version = "=1.0.0-rc.3", features = ["server", "http1", "http2"] }
tokio = { version = "1", features = ["full"] }
http-body-util = "=0.1.0-rc.2"
http = { version = "0.2" }
matchit = { version = "0.7" }
motore = { version = "0.3" }
motore.workspace = true
tracing.workspace = true
futures-util.workspace = true
pin-project-lite = "0.2"
Expand All @@ -28,19 +28,7 @@ serde_json = "1"
thiserror.workspace = true
mime = "0.3"
serde = "1"
async-trait.workspace = true
<<<<<<< HEAD
=======
<<<<<<< HEAD
=======
>>>>>>> init
=======
async-trait.workspace = true
>>>>>>> handler, extractor (#221)
=======
parking_lot.workspace = true
>>>>>>> add graceful shutdown
>>>>>>> de495fd... add graceful shutdown

[dev-dependencies]
serde = { version = "1", features = ["derive"] }
41 changes: 17 additions & 24 deletions volo-http/src/dispatch.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{future::Future, marker::PhantomData};
use std::marker::PhantomData;

use http::Response;
use hyper::body::Incoming;
Expand Down Expand Up @@ -41,34 +41,27 @@ where
S::Error: std::error::Error + Send + Sync + 'static,
OB: Into<RespBody>,
IB: FromRequest + Send,
for<'cx> <IB as FromRequest>::FromFut<'cx>: std::marker::Send,
{
type Response = Response<RespBody>;

type Error = DynError;

type Future<'cx> = impl Future<Output = Result<Self::Response, Self::Error>> + Send + 'cx
where
HttpContext: 'cx,
Self: 'cx;

fn call<'cx, 's>(&'s self, cx: &'cx mut HttpContext, req: Incoming) -> Self::Future<'cx>
where
's: 'cx,
{
async move {
match IB::from(&*cx, req).await {
Ok(body) => self
.inner
.call(cx, body)
.await
.map(|resp| {
let (parts, body) = resp.into_parts();
Response::from_parts(parts, body.into())
})
.map_err(|e| Box::new(e) as DynError),
Err(response) => Ok(response),
}
async fn call<'s, 'cx>(
&'s self,
cx: &'cx mut HttpContext,
req: Incoming,
) -> Result<Self::Response, Self::Error> {
match IB::from(&*cx, req).await {
Ok(body) => self
.inner
.call(cx, body)
.await
.map(|resp| {
let (parts, body) = resp.into_parts();
Response::from_parts(parts, body.into())
})
.map_err(|e| Box::new(e) as DynError),
Err(response) => Ok(response),
}
}
}
22 changes: 13 additions & 9 deletions volo-http/src/extract.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,38 @@
use futures_util::Future;
use http::{Method, Response, Uri};

use crate::{response::IntoResponse, HttpContext};

#[async_trait::async_trait]
pub trait FromContext: Sized {
type Rejection: IntoResponse;
async fn from_context(context: &HttpContext) -> Result<Self, Self::Rejection>;
fn from_context(
context: &HttpContext,
) -> impl Future<Output = Result<Self, Self::Rejection>> + Send;
}
#[async_trait::async_trait]

impl<T> FromContext for Option<T>
where
T: FromContext,
{
type Rejection = Response<()>; // Infallible

async fn from_context(context: &HttpContext) -> Result<Self, Self::Rejection> {
Ok(T::from_context(context).await.ok())
fn from_context(
context: &HttpContext,
) -> impl Future<Output = Result<Self, Self::Rejection>> + Send {
async move { Ok(T::from_context(context).await.ok()) }
}
}

#[async_trait::async_trait]
impl FromContext for Uri {
type Rejection = Response<()>; // Infallible

async fn from_context(context: &HttpContext) -> Result<Uri, Self::Rejection> {
Ok(context.uri.clone())
fn from_context(
context: &HttpContext,
) -> impl Future<Output = Result<Uri, Self::Rejection>> + Send {
async move { Ok(context.uri.clone()) }
}
}

#[async_trait::async_trait]
impl FromContext for Method {
type Rejection = Response<()>;

Expand Down
49 changes: 21 additions & 28 deletions volo-http/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ where
}
}
pub trait Handler<T> {
type Future<'r>: Future<Output = Response<RespBody>> + Send + 'r
where
Self: 'r;
fn call(self, context: &mut HttpContext, req: Incoming) -> Self::Future<'_>;
fn call(
self,
context: &mut HttpContext,
req: Incoming,
) -> impl Future<Output = Response<RespBody>> + Send;
}

macro_rules! impl_handler {
Expand All @@ -41,23 +42,18 @@ macro_rules! impl_handler {
for<'r> $last: FromRequest + Send + 'r,
Res: IntoResponse,
{
type Future<'r> = impl Future<Output=Response<RespBody>> + Send + 'r
where Self: 'r;

fn call(self, context: &mut HttpContext, req: Incoming) -> Self::Future<'_> {
async move {
$(
let $ty = match $ty::from_context(context).await {
Ok(value) => value,
Err(rejection) => return rejection.into_response(),
};
)*
let $last = match $last::from(context, req).await {
async fn call(self, context: &mut HttpContext, req: Incoming) -> Response<RespBody> {
$(
let $ty = match $ty::from_context(context).await {
Ok(value) => value,
Err(rejection) => return rejection,
Err(rejection) => return rejection.into_response(),
};
self($($ty,)* $last).await.into_response()
}
)*
let $last = match $last::from(context, req).await {
Ok(value) => value,
Err(rejection) => return rejection,
};
self($($ty,)* $last).await.into_response()
}
}
};
Expand Down Expand Up @@ -109,15 +105,12 @@ where
{
type Response = Response<RespBody>;
type Error = http::Error;
type Future<'cx> = impl Future<Output = Result<Self::Response, Self::Error>> + Send + 'cx
where
HttpContext: 'cx,
Self: 'cx;

fn call<'cx, 's>(&'s self, cx: &'cx mut HttpContext, req: Incoming) -> Self::Future<'cx>
where
's: 'cx,
{
async move { Ok(self.h.clone().call(cx, req).await) }
async fn call<'s, 'cx>(
&'s self,
cx: &'cx mut HttpContext,
req: Incoming,
) -> Result<Self::Response, Self::Error> {
Ok(self.h.clone().call(cx, req).await)
}
}
28 changes: 8 additions & 20 deletions volo-http/src/layer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::future::Future;

use http::{Method, Request, Response, StatusCode};
use http_body_util::Full;
use hyper::body::{Bytes, Incoming};
Expand Down Expand Up @@ -79,27 +77,17 @@ where

type Error = S::Error;

type Future<'cx> = impl Future<Output = Result<Self::Response, Self::Error>> + Send + 'cx
where
HttpContext: 'cx,
Self: 'cx;

fn call<'cx, 's>(
async fn call<'s, 'cx>(
&'s self,
cx: &'cx mut HttpContext,
req: Request<Incoming>,
) -> Self::Future<'cx>
where
's: 'cx,
{
async move {
if let Err(status) = (self.f)(cx, &req) {
return Ok(Response::builder()
.status(status)
.body(Full::new(Bytes::new()))
.unwrap());
}
self.service.call(cx, req).await
) -> Result<Self::Response, Self::Error> {
if let Err(status) = (self.f)(cx, &req) {
return Ok(Response::builder()
.status(status)
.body(Full::new(Bytes::new()))
.unwrap());
}
self.service.call(cx, req).await
}
}
4 changes: 3 additions & 1 deletion volo-http/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ where
version: parts.version,
headers: parts.headers,
extensions: parts.extensions,
params: Params { inner: Vec::with_capacity(0) },
params: Params {
inner: Vec::with_capacity(0),
},
};
s.call(&mut cx, req).await
}
Expand Down
36 changes: 16 additions & 20 deletions volo-http/src/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,20 @@ use crate::{
};

pub trait FromRequest: Sized {
type FromFut<'cx>: Future<Output = Result<Self, Response<RespBody>>> + Send + 'cx
where
Self: 'cx;

fn from(cx: &HttpContext, body: Incoming) -> Self::FromFut<'_>;
fn from(
cx: &HttpContext,
body: Incoming,
) -> impl Future<Output = Result<Self, Response<RespBody>>> + Send;
}

impl<T> FromRequest for T
where
T: FromContext,
{
type FromFut<'cx> = impl Future<Output = Result<Self, Response<RespBody>>> + Send + 'cx
where
Self: 'cx;

fn from(cx: &HttpContext, _body: Incoming) -> Self::FromFut<'_> {
fn from(
cx: &HttpContext,
_body: Incoming,
) -> impl Future<Output = Result<Self, Response<RespBody>>> + Send {
async move {
match T::from_context(cx).await {
Ok(value) => Ok(value),
Expand All @@ -38,23 +36,21 @@ where
}

impl FromRequest for Incoming {
type FromFut<'cx> = impl Future<Output = Result<Self, Response<RespBody>>> + Send + 'cx
where
Self: 'cx;

fn from(_cx: &HttpContext, body: Incoming) -> Self::FromFut<'_> {
fn from(
_cx: &HttpContext,
body: Incoming,
) -> impl Future<Output = Result<Self, Response<RespBody>>> + Send {
async { Ok(body) }
}
}

pub struct Json<T>(pub T);

impl<T: DeserializeOwned> FromRequest for Json<T> {
type FromFut<'cx> = impl Future<Output = Result<Self, Response<RespBody>>> + Send + 'cx
where
Self: 'cx;

fn from(cx: &HttpContext, body: Incoming) -> Self::FromFut<'_> {
fn from(
cx: &HttpContext,
body: Incoming,
) -> impl Future<Output = Result<Self, Response<RespBody>>> + Send {
async move {
if !json_content_type(&cx.headers) {
return Err(Response::builder()
Expand Down
Loading

0 comments on commit da44579

Please sign in to comment.