diff --git a/rama-core/src/matcher/mfn.rs b/rama-core/src/matcher/mfn.rs index e14b5136..c36b8cbf 100644 --- a/rama-core/src/matcher/mfn.rs +++ b/rama-core/src/matcher/mfn.rs @@ -14,76 +14,38 @@ pub fn match_fn(f: F) -> MatchFnBox { /// /// You do not need to implement this trait yourself. /// Instead, you need to use the [`match_fn`] function to create a [`MatchFn`]. -pub trait MatchFn: private::Sealed + Send + Sync + 'static { - /// returns true on a match, false otherwise - /// - /// `ext` is None in case the callee is not interested in collecting potential - /// match metadata gathered during the matching process. An example of this - /// path parameters for an http Uri matcher. - fn call(&self, ext: Option<&mut Extensions>, ctx: &Context, req: &Request) -> bool; -} +pub trait MatchFn: private::Sealed + Send + Sync + 'static {} -impl MatchFn for F -where - F: Fn() -> bool + Send + Sync + 'static, -{ - fn call(&self, _ext: Option<&mut Extensions>, _ctx: &Context, _req: &Request) -> bool { - (self)() - } -} +impl MatchFn for F where F: Fn() -> bool + Send + Sync + 'static {} -impl MatchFn for F -where - F: Fn(&Request) -> bool + Send + Sync + 'static, +impl MatchFn for F where + F: Fn(&Request) -> bool + Send + Sync + 'static { - fn call(&self, _ext: Option<&mut Extensions>, _ctx: &Context, req: &Request) -> bool { - (self)(req) - } } -impl MatchFn, Request)> for F -where - F: Fn(&Context, &Request) -> bool + Send + Sync + 'static, +impl MatchFn, Request)> for F where + F: Fn(&Context, &Request) -> bool + Send + Sync + 'static { - fn call(&self, _ext: Option<&mut Extensions>, ctx: &Context, req: &Request) -> bool { - (self)(ctx, req) - } } -impl MatchFn, Context, Request)> for F -where - F: Fn(Option<&mut Extensions>, &Context, &Request) -> bool + Send + Sync + 'static, +impl MatchFn, Context, Request)> for F where + F: Fn(Option<&mut Extensions>, &Context, &Request) -> bool + Send + Sync + 'static { - fn call(&self, ext: Option<&mut Extensions>, ctx: &Context, req: &Request) -> bool { - (self)(ext, ctx, req) - } } -impl MatchFn, Request)> for F -where - F: Fn(Option<&mut Extensions>, &Request) -> bool + Send + Sync + 'static, +impl MatchFn, Request)> for F where + F: Fn(Option<&mut Extensions>, &Request) -> bool + Send + Sync + 'static { - fn call(&self, ext: Option<&mut Extensions>, _ctx: &Context, req: &Request) -> bool { - (self)(ext, req) - } } -impl MatchFn)> for F -where - F: Fn(Option<&mut Extensions>) -> bool + Send + Sync + 'static, +impl MatchFn)> for F where + F: Fn(Option<&mut Extensions>) -> bool + Send + Sync + 'static { - fn call(&self, ext: Option<&mut Extensions>, _ctx: &Context, _req: &Request) -> bool { - (self)(ext) - } } -impl MatchFn)> for F -where - F: Fn(&Context) -> bool + Send + Sync + 'static, +impl MatchFn)> for F where + F: Fn(&Context) -> bool + Send + Sync + 'static { - fn call(&self, _ext: Option<&mut Extensions>, ctx: &Context, _req: &Request) -> bool { - (self)(ctx) - } } impl @@ -91,9 +53,6 @@ impl where F: Fn(Option<&mut Extensions>, &Context) -> bool + Send + Sync + 'static, { - fn call(&self, ext: Option<&mut Extensions>, ctx: &Context, _req: &Request) -> bool { - (self)(ext, ctx) - } } /// The public wrapper type for [`MatchFn`]. @@ -133,34 +92,76 @@ where mod private { use super::*; - pub trait Sealed {} + pub trait Sealed { + /// returns true on a match, false otherwise + /// + /// `ext` is None in case the callee is not interested in collecting potential + /// match metadata gathered during the matching process. An example of this + /// path parameters for an http Uri matcher. + fn call(&self, ext: Option<&mut Extensions>, ctx: &Context, req: &Request) -> bool; + } + + impl Sealed for F + where + F: Fn() -> bool + Send + Sync + 'static, + { + fn call(&self, _ext: Option<&mut Extensions>, _ctx: &Context, _req: &Request) -> bool { + (self)() + } + } - impl Sealed for F where F: Fn() -> bool + Send + Sync + 'static {} - impl Sealed for F where - F: Fn(&Request) -> bool + Send + Sync + 'static + impl Sealed for F + where + F: Fn(&Request) -> bool + Send + Sync + 'static, { + fn call(&self, _ext: Option<&mut Extensions>, _ctx: &Context, req: &Request) -> bool { + (self)(req) + } } - impl Sealed, Request)> for F where - F: Fn(&Context, &Request) -> bool + Send + Sync + 'static + + impl Sealed, Request)> for F + where + F: Fn(&Context, &Request) -> bool + Send + Sync + 'static, { + fn call(&self, _ext: Option<&mut Extensions>, ctx: &Context, req: &Request) -> bool { + (self)(ctx, req) + } } - impl Sealed, Context, Request)> for F where - F: Fn(Option<&mut Extensions>, &Context, &Request) -> bool + Send + Sync + 'static + + impl Sealed, Context, Request)> for F + where + F: Fn(Option<&mut Extensions>, &Context, &Request) -> bool + Send + Sync + 'static, { + fn call(&self, ext: Option<&mut Extensions>, ctx: &Context, req: &Request) -> bool { + (self)(ext, ctx, req) + } } - impl Sealed, Request)> for F where - F: Fn(Option<&mut Extensions>, &Request) -> bool + Send + Sync + 'static + + impl Sealed, Request)> for F + where + F: Fn(Option<&mut Extensions>, &Request) -> bool + Send + Sync + 'static, { + fn call(&self, ext: Option<&mut Extensions>, _ctx: &Context, req: &Request) -> bool { + (self)(ext, req) + } } - impl Sealed)> for F where - F: Fn(Option<&mut Extensions>) -> bool + Send + Sync + 'static + impl Sealed)> for F + where + F: Fn(Option<&mut Extensions>) -> bool + Send + Sync + 'static, { + fn call(&self, ext: Option<&mut Extensions>, _ctx: &Context, _req: &Request) -> bool { + (self)(ext) + } } - impl Sealed)> for F where - F: Fn(&Context) -> bool + Send + Sync + 'static + impl Sealed)> for F + where + F: Fn(&Context) -> bool + Send + Sync + 'static, { + fn call(&self, _ext: Option<&mut Extensions>, ctx: &Context, _req: &Request) -> bool { + (self)(ctx) + } } impl @@ -168,5 +169,8 @@ mod private { where F: Fn(Option<&mut Extensions>, &Context) -> bool + Send + Sync + 'static, { + fn call(&self, ext: Option<&mut Extensions>, ctx: &Context, _req: &Request) -> bool { + (self)(ext, ctx) + } } } diff --git a/rama-http-backend/src/server/hyper_conn.rs b/rama-http-backend/src/server/hyper_conn.rs index ac8c1f16..63210d32 100644 --- a/rama-http-backend/src/server/hyper_conn.rs +++ b/rama-http-backend/src/server/hyper_conn.rs @@ -1,162 +1,20 @@ -use super::{svc_hyper::HyperService, HttpServeResult}; +use super::HttpServeResult; use crate::executor::HyperExecutor; use hyper::server::conn::http1::Builder as Http1Builder; use hyper::server::conn::http2::Builder as Http2Builder; -use hyper_util::{rt::TokioIo, server::conn::auto::Builder as AutoBuilder}; -use rama_core::{Context, Service}; -use rama_http_types::{IntoResponse, Request}; -use rama_net::stream::Stream; +use hyper_util::server::conn::auto::Builder as AutoBuilder; use rama_tcp::utils::is_connection_error; -use rama_utils::future::Fuse; -use std::convert::Infallible; use std::error::Error; -use std::pin::pin; -use tokio::select; /// A utility trait to allow any of the hyper server builders to be used /// in the same way to (http) serve a connection. -pub trait HyperConnServer: Send + Sync + private::Sealed + 'static { - fn hyper_serve_connection( - &self, - ctx: Context, - io: IO, - service: S, - ) -> impl std::future::Future + Send + '_ - where - IO: Stream, - State: Clone + Send + Sync + 'static, - S: Service, - Response: IntoResponse + Send + 'static; -} +pub trait HyperConnServer: Send + Sync + private::Sealed + 'static {} -impl HyperConnServer for Http1Builder { - #[inline] - async fn hyper_serve_connection( - &self, - ctx: Context, - io: IO, - service: S, - ) -> HttpServeResult - where - IO: Stream, - State: Clone + Send + Sync + 'static, - S: Service, - Response: IntoResponse + Send + 'static, - { - let stream = TokioIo::new(Box::pin(io)); - let guard = ctx.guard().cloned(); - let service = HyperService::new(ctx, service); - - let mut conn = pin!(self.serve_connection(stream, service).with_upgrades()); - - if let Some(guard) = guard { - let mut cancelled_fut = pin!(Fuse::new(guard.cancelled())); - - select! { - _ = cancelled_fut.as_mut() => { - tracing::trace!("signal received: initiate graceful shutdown"); - conn.as_mut().graceful_shutdown(); - } - result = conn.as_mut() => { - tracing::trace!("connection finished"); - return map_hyper_result(result); - } - } +impl HyperConnServer for Http1Builder {} - let result = conn.as_mut().await; - tracing::trace!("connection finished after graceful shutdown"); - map_hyper_result(result) - } else { - map_hyper_result(conn.await) - } - } -} +impl HyperConnServer for Http2Builder {} -impl HyperConnServer for Http2Builder { - #[inline] - async fn hyper_serve_connection( - &self, - ctx: Context, - io: IO, - service: S, - ) -> HttpServeResult - where - IO: Stream, - State: Clone + Send + Sync + 'static, - S: Service, - Response: IntoResponse + Send + 'static, - { - let stream = TokioIo::new(Box::pin(io)); - let guard = ctx.guard().cloned(); - let service = HyperService::new(ctx, service); - - let mut conn = pin!(self.serve_connection(stream, service)); - - if let Some(guard) = guard { - let mut cancelled_fut = pin!(Fuse::new(guard.cancelled())); - - select! { - _ = cancelled_fut.as_mut() => { - tracing::trace!("signal received: initiate graceful shutdown"); - conn.as_mut().graceful_shutdown(); - } - result = conn.as_mut() => { - tracing::trace!("connection finished"); - return map_hyper_result(result); - } - } - - let result = conn.as_mut().await; - tracing::trace!("connection finished after graceful shutdown"); - map_hyper_result(result) - } else { - map_hyper_result(conn.await) - } - } -} - -impl HyperConnServer for AutoBuilder { - #[inline] - async fn hyper_serve_connection( - &self, - ctx: Context, - io: IO, - service: S, - ) -> HttpServeResult - where - IO: Stream, - State: Clone + Send + Sync + 'static, - S: Service, - Response: IntoResponse + Send + 'static, - { - let stream = TokioIo::new(Box::pin(io)); - let guard = ctx.guard().cloned(); - let service = HyperService::new(ctx, service); - - let mut conn = pin!(self.serve_connection_with_upgrades(stream, service)); - - if let Some(guard) = guard { - let mut cancelled_fut = pin!(Fuse::new(guard.cancelled())); - - select! { - _ = cancelled_fut.as_mut() => { - tracing::trace!("signal received: nop: graceful shutdown not supported for auto builder"); - conn.as_mut().graceful_shutdown(); - } - result = conn.as_mut() => { - tracing::trace!("connection finished"); - return map_boxed_hyper_result(result); - } - } - - let result = conn.as_mut().await; - tracing::trace!("connection finished after graceful shutdown"); - map_boxed_hyper_result(result) - } else { - map_boxed_hyper_result(conn.await) - } - } -} +impl HyperConnServer for AutoBuilder {} /// A utility function to map boxed, potentially hyper errors, to our own error type. fn map_boxed_hyper_result( @@ -211,10 +69,157 @@ fn map_hyper_err_to_result(err: hyper::Error) -> HttpServeResult { mod private { use crate::executor::HyperExecutor; + use crate::server::hyper_conn::{map_boxed_hyper_result, map_hyper_result}; + use crate::server::{svc_hyper::HyperService, HttpServeResult}; + use hyper_util::rt::TokioIo; + use rama_core::{Context, Service}; + use rama_http_types::{IntoResponse, Request}; + use rama_net::stream::Stream; + use rama_utils::future::Fuse; + use std::convert::Infallible; + use std::pin::pin; + use tokio::select; + + pub trait Sealed { + fn hyper_serve_connection( + &self, + ctx: Context, + io: IO, + service: S, + ) -> impl std::future::Future + Send + '_ + where + IO: Stream, + State: Clone + Send + Sync + 'static, + S: Service, + Response: IntoResponse + Send + 'static; + } - pub trait Sealed {} + impl Sealed for super::Http1Builder { + #[inline] + async fn hyper_serve_connection( + &self, + ctx: Context, + io: IO, + service: S, + ) -> HttpServeResult + where + IO: Stream, + State: Clone + Send + Sync + 'static, + S: Service, + Response: IntoResponse + Send + 'static, + { + let stream = TokioIo::new(Box::pin(io)); + let guard = ctx.guard().cloned(); + let service = HyperService::new(ctx, service); + + let mut conn = pin!(self.serve_connection(stream, service).with_upgrades()); + + if let Some(guard) = guard { + let mut cancelled_fut = pin!(Fuse::new(guard.cancelled())); + + select! { + _ = cancelled_fut.as_mut() => { + tracing::trace!("signal received: initiate graceful shutdown"); + conn.as_mut().graceful_shutdown(); + } + result = conn.as_mut() => { + tracing::trace!("connection finished"); + return map_hyper_result(result); + } + } + + let result = conn.as_mut().await; + tracing::trace!("connection finished after graceful shutdown"); + map_hyper_result(result) + } else { + map_hyper_result(conn.await) + } + } + } + + impl Sealed for super::Http2Builder { + #[inline] + async fn hyper_serve_connection( + &self, + ctx: Context, + io: IO, + service: S, + ) -> HttpServeResult + where + IO: Stream, + State: Clone + Send + Sync + 'static, + S: Service, + Response: IntoResponse + Send + 'static, + { + let stream = TokioIo::new(Box::pin(io)); + let guard = ctx.guard().cloned(); + let service = HyperService::new(ctx, service); + + let mut conn = pin!(self.serve_connection(stream, service)); + + if let Some(guard) = guard { + let mut cancelled_fut = pin!(Fuse::new(guard.cancelled())); + + select! { + _ = cancelled_fut.as_mut() => { + tracing::trace!("signal received: initiate graceful shutdown"); + conn.as_mut().graceful_shutdown(); + } + result = conn.as_mut() => { + tracing::trace!("connection finished"); + return map_hyper_result(result); + } + } - impl Sealed for super::Http1Builder {} - impl Sealed for super::Http2Builder {} - impl Sealed for super::AutoBuilder {} + let result = conn.as_mut().await; + tracing::trace!("connection finished after graceful shutdown"); + map_hyper_result(result) + } else { + map_hyper_result(conn.await) + } + } + } + + impl Sealed for super::AutoBuilder { + #[inline] + async fn hyper_serve_connection( + &self, + ctx: Context, + io: IO, + service: S, + ) -> HttpServeResult + where + IO: Stream, + State: Clone + Send + Sync + 'static, + S: Service, + Response: IntoResponse + Send + 'static, + { + let stream = TokioIo::new(Box::pin(io)); + let guard = ctx.guard().cloned(); + let service = HyperService::new(ctx, service); + + let mut conn = pin!(self.serve_connection_with_upgrades(stream, service)); + + if let Some(guard) = guard { + let mut cancelled_fut = pin!(Fuse::new(guard.cancelled())); + + select! { + _ = cancelled_fut.as_mut() => { + tracing::trace!("signal received: nop: graceful shutdown not supported for auto builder"); + conn.as_mut().graceful_shutdown(); + } + result = conn.as_mut() => { + tracing::trace!("connection finished"); + return map_boxed_hyper_result(result); + } + } + + let result = conn.as_mut().await; + tracing::trace!("connection finished after graceful shutdown"); + map_boxed_hyper_result(result) + } else { + map_boxed_hyper_result(conn.await) + } + } + } } diff --git a/rama-http/src/service/web/endpoint/service.rs b/rama-http/src/service/web/endpoint/service.rs index 6e913bf5..ebada7f2 100644 --- a/rama-http/src/service/web/endpoint/service.rs +++ b/rama-http/src/service/web/endpoint/service.rs @@ -5,13 +5,7 @@ use rama_utils::macros::all_the_tuples_no_last_special_case; use std::future::Future; /// [`rama_core::Service`] implemented for functions taking extractors. -pub trait EndpointServiceFn: private::Sealed + Clone + Send + Sync + 'static { - /// Serve a response for the given request. - /// - /// It is expected to do so by extracting the desired data from the context and/or request, - /// and then calling the function with the extracted data. - fn call(&self, ctx: Context, req: Request) -> impl Future + Send + '_; -} +pub trait EndpointServiceFn: private::Sealed + Clone + Send + Sync + 'static {} impl EndpointServiceFn for F where @@ -20,9 +14,6 @@ where O: IntoResponse + Send + Sync + 'static, S: Clone + Send + Sync + 'static, { - async fn call(&self, _ctx: Context, _req: Request) -> Response { - self().await.into_response() - } } impl EndpointServiceFn for F @@ -33,13 +24,6 @@ where S: Clone + Send + Sync + 'static, I: FromRequest, { - async fn call(&self, _ctx: Context, req: Request) -> Response { - let param: I = match I::from_request(req).await { - Ok(v) => v, - Err(r) => return r.into_response(), - }; - self(param).await.into_response() - } } impl EndpointServiceFn)> for F @@ -49,9 +33,6 @@ where O: IntoResponse + Send + Sync + 'static, S: Clone + Send + Sync + 'static, { - async fn call(&self, ctx: Context, _req: Request) -> Response { - self(ctx).await.into_response() - } } impl EndpointServiceFn, I)> for F @@ -62,13 +43,6 @@ where S: Clone + Send + Sync + 'static, I: FromRequest, { - async fn call(&self, ctx: Context, req: Request) -> Response { - let param: I = match I::from_request(req).await { - Ok(v) => v, - Err(r) => return r.into_response(), - }; - self(ctx, param).await.into_response() - } } macro_rules! impl_endpoint_service_fn_tuple { @@ -82,14 +56,6 @@ macro_rules! impl_endpoint_service_fn_tuple { S: Clone + Send + Sync + 'static, $($ty: FromRequestContextRefPair),+, { - async fn call(&self, ctx: Context, req: Request) -> Response { - let (parts, _body) = req.into_parts(); - $(let $ty = match $ty::from_request_context_ref_pair(&ctx, &parts).await { - Ok(v) => v, - Err(r) => return r.into_response(), - });+; - self($($ty),+).await.into_response() - } } }; } @@ -108,19 +74,6 @@ macro_rules! impl_endpoint_service_fn_tuple_with_from_request { $($ty: FromRequestContextRefPair),+, I: FromRequest, { - async fn call(&self, ctx: Context, req: Request) -> Response { - let (parts, body) = req.into_parts(); - $(let $ty = match $ty::from_request_context_ref_pair(&ctx, &parts).await { - Ok(v) => v, - Err(r) => return r.into_response(), - });+; - let req = Request::from_parts(parts, body); - let last: I = match I::from_request(req).await { - Ok(v) => v, - Err(r) => return r.into_response(), - }; - self($($ty),+, last).await.into_response() - } } }; } @@ -138,14 +91,6 @@ macro_rules! impl_endpoint_service_fn_tuple_with_context { S: Clone + Send + Sync + 'static, $($ty: FromRequestContextRefPair),+, { - async fn call(&self, ctx: Context, req: Request) -> Response { - let (parts, _body) = req.into_parts(); - $(let $ty = match $ty::from_request_context_ref_pair(&ctx, &parts).await { - Ok(v) => v, - Err(r) => return r.into_response(), - });+; - self($($ty),+, ctx).await.into_response() - } } }; } @@ -164,19 +109,6 @@ macro_rules! impl_endpoint_service_fn_tuple_with_context_and_from_request { $($ty: FromRequestContextRefPair),+, I: FromRequest, { - async fn call(&self, ctx: Context, req: Request) -> Response { - let (parts, body) = req.into_parts(); - $(let $ty = match $ty::from_request_context_ref_pair(&ctx, &parts).await { - Ok(v) => v, - Err(r) => return r.into_response(), - });+; - let req = Request::from_parts(parts, body); - let last: I = match I::from_request(req).await { - Ok(v) => v, - Err(r) => return r.into_response(), - }; - self($($ty),+, ctx, last).await.into_response() - } } }; } @@ -186,7 +118,14 @@ all_the_tuples_no_last_special_case!(impl_endpoint_service_fn_tuple_with_context mod private { use super::*; - pub trait Sealed {} + pub trait Sealed { + /// Serve a response for the given request. + /// + /// It is expected to do so by extracting the desired data from the context and/or request, + /// and then calling the function with the extracted data. + fn call(&self, ctx: Context, req: Request) + -> impl Future + Send + '_; + } impl Sealed for F where @@ -195,6 +134,9 @@ mod private { O: IntoResponse + Send + Sync + 'static, S: Clone + Send + Sync + 'static, { + async fn call(&self, _ctx: Context, _req: Request) -> Response { + self().await.into_response() + } } impl Sealed for F @@ -205,6 +147,13 @@ mod private { S: Clone + Send + Sync + 'static, I: FromRequest, { + async fn call(&self, _ctx: Context, req: Request) -> Response { + let param: I = match I::from_request(req).await { + Ok(v) => v, + Err(r) => return r.into_response(), + }; + self(param).await.into_response() + } } impl Sealed)> for F @@ -214,6 +163,9 @@ mod private { O: IntoResponse + Send + Sync + 'static, S: Clone + Send + Sync + 'static, { + async fn call(&self, ctx: Context, _req: Request) -> Response { + self(ctx).await.into_response() + } } impl Sealed, I)> for F @@ -224,6 +176,13 @@ mod private { S: Clone + Send + Sync + 'static, I: FromRequest, { + async fn call(&self, ctx: Context, req: Request) -> Response { + let param: I = match I::from_request(req).await { + Ok(v) => v, + Err(r) => return r.into_response(), + }; + self(ctx, param).await.into_response() + } } macro_rules! impl_endpoint_service_fn_sealed_tuple { @@ -236,7 +195,17 @@ mod private { O: IntoResponse + Send + Sync + 'static, S: Clone + Send + Sync + 'static, $($ty: FromRequestContextRefPair),+, - {} + { + + async fn call(&self, ctx: Context, req: Request) -> Response { + let (parts, _body) = req.into_parts(); + $(let $ty = match $ty::from_request_context_ref_pair(&ctx, &parts).await { + Ok(v) => v, + Err(r) => return r.into_response(), + });+; + self($($ty),+).await.into_response() + } + } }; } @@ -253,7 +222,22 @@ mod private { S: Clone + Send + Sync + 'static, I: FromRequest, $($ty: FromRequestContextRefPair),+, - {} + { + + async fn call(&self, ctx: Context, req: Request) -> Response { + let (parts, body) = req.into_parts(); + $(let $ty = match $ty::from_request_context_ref_pair(&ctx, &parts).await { + Ok(v) => v, + Err(r) => return r.into_response(), + });+; + let req = Request::from_parts(parts, body); + let last: I = match I::from_request(req).await { + Ok(v) => v, + Err(r) => return r.into_response(), + }; + self($($ty),+, last).await.into_response() + } + } }; } @@ -269,7 +253,17 @@ mod private { O: IntoResponse + Send + Sync + 'static, S: Clone + Send + Sync + 'static, $($ty: FromRequestContextRefPair),+, - {} + { + + async fn call(&self, ctx: Context, req: Request) -> Response { + let (parts, _body) = req.into_parts(); + $(let $ty = match $ty::from_request_context_ref_pair(&ctx, &parts).await { + Ok(v) => v, + Err(r) => return r.into_response(), + });+; + self($($ty),+, ctx).await.into_response() + } + } }; } @@ -286,7 +280,22 @@ mod private { S: Clone + Send + Sync + 'static, I: FromRequest, $($ty: FromRequestContextRefPair),+, - {} + { + + async fn call(&self, ctx: Context, req: Request) -> Response { + let (parts, body) = req.into_parts(); + $(let $ty = match $ty::from_request_context_ref_pair(&ctx, &parts).await { + Ok(v) => v, + Err(r) => return r.into_response(), + });+; + let req = Request::from_parts(parts, body); + let last: I = match I::from_request(req).await { + Ok(v) => v, + Err(r) => return r.into_response(), + }; + self($($ty),+, ctx, last).await.into_response() + } + } }; } diff --git a/rama-http/src/service/web/k8s.rs b/rama-http/src/service/web/k8s.rs index b8363687..2c84640c 100644 --- a/rama-http/src/service/web/k8s.rs +++ b/rama-http/src/service/web/k8s.rs @@ -111,25 +111,15 @@ where } /// Utility internal trait to create service endpoints for the different checks -pub trait ToK8sService: private::Sealed { - /// create a boxed web service by consuming self - fn to_k8s_service(self) -> BoxService; -} +pub trait ToK8sService: private::Sealed {} -impl ToK8sService for () { - fn to_k8s_service(self) -> BoxService { - service_fn(|| async { Ok(StatusCode::OK.into_response()) }).boxed() - } -} +impl ToK8sService for () {} impl ToK8sService for F where F: Fn() -> bool + Clone + Send + Sync + 'static, S: Clone + Send + Sync + 'static, { - fn to_k8s_service(self) -> BoxService { - K8sService::new(self).boxed() - } } struct K8sService { @@ -173,8 +163,24 @@ where } mod private { - pub trait Sealed {} + use super::*; + + pub trait Sealed { + /// create a boxed web service by consuming self + fn to_k8s_service(self) -> BoxService; + } - impl Sealed for () {} - impl bool + Clone + Send + Sync + 'static> Sealed for F {} + impl Sealed for () { + fn to_k8s_service(self) -> BoxService { + service_fn(|| async { Ok(StatusCode::OK.into_response()) }).boxed() + } + } + + impl bool + Clone + Send + Sync + 'static> + Sealed for F + { + fn to_k8s_service(self) -> BoxService { + K8sService::new(self).boxed() + } + } } diff --git a/rama-net/src/stream/matcher/ip.rs b/rama-net/src/stream/matcher/ip.rs index 0f271276..8ffeabe7 100644 --- a/rama-net/src/stream/matcher/ip.rs +++ b/rama-net/src/stream/matcher/ip.rs @@ -76,43 +76,20 @@ where } /// utility trait to consume a tpe into an [`IpNet`] -pub trait IntoIpNet: private::Sealed { - /// Consume `self` into an [`IpNet`] - fn into_ip_net(self) -> IpNet; -} - -impl IntoIpNet for Ipv4Net { - fn into_ip_net(self) -> IpNet { - IpNet::V4(self) - } -} - -impl IntoIpNet for Ipv6Net { - fn into_ip_net(self) -> IpNet { - IpNet::V6(self) - } -} - -impl IntoIpNet for IpNet { - fn into_ip_net(self) -> IpNet { - self - } -} +pub trait IntoIpNet: private::Sealed {} macro_rules! impl_ip_net_from_ip_addr_into_all { ($($ty:ty),+ $(,)?) => { $( - impl IntoIpNet for $ty { - fn into_ip_net(self) -> IpNet { - let ip_addr: std::net::IpAddr = self.into(); - ip_addr.into() - } - } + impl IntoIpNet for $ty {} )+ }; } impl_ip_net_from_ip_addr_into_all!( + Ipv4Net, + Ipv6Net, + IpNet, std::net::IpAddr, std::net::Ipv4Addr, std::net::Ipv6Addr, @@ -124,19 +101,50 @@ impl_ip_net_from_ip_addr_into_all!( mod private { use super::*; - pub trait Sealed {} - - impl Sealed for std::net::IpAddr {} - impl Sealed for std::net::Ipv4Addr {} - impl Sealed for std::net::Ipv6Addr {} - impl Sealed for [u16; 8] {} - impl Sealed for [u8; 16] {} - impl Sealed for [u8; 4] {} - impl Sealed for Ipv4Net {} - impl Sealed for Ipv6Net {} - impl Sealed for IpNet {} - impl Sealed for String {} - impl Sealed for &str {} + pub trait Sealed { + /// Consume `self` into an [`IpNet`] + fn into_ip_net(self) -> IpNet; + } + + impl Sealed for Ipv4Net { + fn into_ip_net(self) -> IpNet { + IpNet::V4(self) + } + } + + impl Sealed for Ipv6Net { + fn into_ip_net(self) -> IpNet { + IpNet::V6(self) + } + } + + impl Sealed for IpNet { + fn into_ip_net(self) -> IpNet { + self + } + } + + macro_rules! impl_sealed_from_ip_addr_into_all { + ($($ty:ty),+ $(,)?) => { + $( + impl Sealed for $ty { + fn into_ip_net(self) -> IpNet { + let ip_addr: std::net::IpAddr = self.into(); + ip_addr.into() + } + } + )+ + }; + } + + impl_sealed_from_ip_addr_into_all!( + std::net::IpAddr, + std::net::Ipv4Addr, + std::net::Ipv6Addr, + [u16; 8], + [u8; 16], + [u8; 4], + ); } #[cfg(test)]