Skip to main content
Glama
handler.rs6.37 kB
use core::fmt; use std::{ convert::Infallible, future::{ Future, Ready, ready, }, marker::PhantomData, pin::Pin, }; use tower::{ Layer, Service, ServiceExt, }; use crate::{ extract::{ FromMessage, FromMessageHead, }, make_service::IntoMakeService, message::{ Message, MessageHead, }, response::{ IntoResponse, Response, }, }; pub mod future; mod service; pub use self::service::HandlerService; pub trait Handler<T, S, R>: Clone + Send + Sized + 'static where R: MessageHead, { type Future: Future<Output = Response> + Send + 'static; fn call(self, req: Message<R>, state: S) -> Self::Future; fn layer<L>(self, layer: L) -> Layered<L, Self, T, S, R> where L: Layer<HandlerService<Self, T, S, R>> + Clone, L::Service: Service<Message<R>>, { Layered { layer, handler: self, _marker: PhantomData, _request_marker: PhantomData, } } fn with_state(self, state: S) -> HandlerService<Self, T, S, R> { HandlerService::new(self, state) } } impl<F, Fut, Res, S, R> Handler<((),), S, R> for F where F: FnOnce() -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, Res: IntoResponse, R: MessageHead, { type Future = Pin<Box<dyn Future<Output = Response> + Send>>; fn call(self, _req: Message<R>, _state: S) -> 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, S, R, Res, M, $($ty,)* $last> Handler<(M, $($ty,)* $last,), S, R> for F where F: FnOnce($($ty,)* $last,) -> Fut + Clone + Send + 'static, Fut: Future<Output = Res> + Send, S: Send + Sync + 'static, R: MessageHead + Send + 'static, Res: IntoResponse, $( $ty: FromMessageHead<S> + Send, )* $last: FromMessage<S, R, M> + Send, { type Future = Pin<Box<dyn Future<Output = Response> + Send>>; fn call(self, req: Message<R>, state: S) -> Self::Future { Box::pin(async move { let (mut parts, body) = req.into_parts(); let state = &state; $( let $ty = match $ty::from_message_head(&mut parts, state).await { Ok(value) => value, Err(rejection) => return rejection.into_response(), }; )* let req = match Message::from_parts(parts, body) { Ok(value) => value, Err(rejection) => return rejection.into_response(), }; let $last = match $last::from_message(req, state).await { Ok(value) => value, Err(rejection) => return rejection.into_response(), }; let res = self($($ty,)* $last,).await; res.into_response() }) } } }; } all_the_tuples!(impl_handler); mod private { // Marker type for `impl<T: IntoResponse> Handler for T` #[allow(missing_debug_implementations)] pub enum IntoResponseHandler {} } impl<T, S, R> Handler<private::IntoResponseHandler, S, R> for T where T: IntoResponse + Clone + Send + 'static, R: MessageHead, { type Future = Ready<Response>; fn call(self, _req: Message<R>, _state: S) -> Self::Future { #[allow(clippy::unit_arg)] ready(self.into_response()) } } pub struct Layered<L, H, T, S, R> { layer: L, handler: H, _marker: PhantomData<fn() -> (T, S)>, _request_marker: PhantomData<R>, } impl<L, H, T, S, R> fmt::Debug for Layered<L, H, T, S, R> where L: fmt::Debug, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Layered") .field("layer", &self.layer) .finish_non_exhaustive() } } impl<L, H, T, S, R> Clone for Layered<L, H, T, S, R> where L: Clone, H: Clone, { fn clone(&self) -> Self { Self { layer: self.layer.clone(), handler: self.handler.clone(), _marker: PhantomData, _request_marker: PhantomData, } } } impl<L, H, T, S, R> Handler<T, S, R> for Layered<L, H, T, S, R> where L: Layer<HandlerService<H, T, S, R>> + Clone + Send + 'static, H: Handler<T, S, R>, L::Service: Service<Message<R>, Error = Infallible> + Clone + Send + 'static, <L::Service as Service<Message<R>>>::Response: IntoResponse, <L::Service as Service<Message<R>>>::Future: Send, T: 'static, S: 'static, R: MessageHead + Send + 'static, { type Future = future::LayeredFuture<L::Service, R>; fn call(self, req: Message<R>, state: S) -> Self::Future { use futures::future::{ FutureExt, Map, }; let svc = self.handler.with_state(state); let svc = self.layer.layer(svc); #[allow(clippy::type_complexity)] let future: Map< _, fn( Result< <L::Service as Service<Message<R>>>::Response, <L::Service as Service<Message<R>>>::Error, >, ) -> _, > = svc.oneshot(req).map(|result| match result { Ok(res) => res.into_response(), Err(err) => match err {}, }); future::LayeredFuture::new(future) } } pub trait HandlerWithoutStateExt<T, R>: Handler<T, (), R> where R: MessageHead, { fn into_service(self) -> HandlerService<Self, T, (), R>; fn into_make_service(self) -> IntoMakeService<HandlerService<Self, T, (), R>>; } impl<H, T, R> HandlerWithoutStateExt<T, R> for H where H: Handler<T, (), R>, R: MessageHead, { fn into_service(self) -> HandlerService<Self, T, (), R> { self.with_state(()) } fn into_make_service(self) -> IntoMakeService<HandlerService<Self, T, (), R>> { self.into_service().into_make_service() } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server