rama_http_core/
service.rs1use bytes::Bytes;
2use rama_core::{Context, Service, error::BoxError};
3use rama_http::service::web::response::IntoResponse;
4use rama_http_types::{Request, Response};
5use std::{convert::Infallible, fmt};
6
7pub trait HttpService<ReqBody>: sealed::Sealed<ReqBody> {
8 #[doc(hidden)]
9 fn serve_http(
10 &self,
11 req: Request<ReqBody>,
12 ) -> impl Future<Output = Result<Response, Infallible>> + Send + 'static;
13}
14
15pub struct RamaHttpService<S, State> {
16 svc: S,
17 ctx: Context<State>,
18}
19
20impl<S, State> RamaHttpService<S, State> {
21 pub fn new(ctx: Context<State>, svc: S) -> Self {
22 Self { svc, ctx }
23 }
24}
25
26impl<S, State> fmt::Debug for RamaHttpService<S, State>
27where
28 S: fmt::Debug,
29 State: fmt::Debug,
30{
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 f.debug_struct("RamaHttpService")
33 .field("svc", &self.svc)
34 .field("ctx", &self.ctx)
35 .finish()
36 }
37}
38
39impl<S, State> Clone for RamaHttpService<S, State>
40where
41 S: Clone,
42 State: Clone,
43{
44 fn clone(&self) -> Self {
45 Self {
46 svc: self.svc.clone(),
47 ctx: self.ctx.clone(),
48 }
49 }
50}
51
52impl<S, State, ReqBody, R> HttpService<ReqBody> for RamaHttpService<S, State>
53where
54 S: Service<State, Request, Response = R, Error = Infallible> + Clone,
55 State: Clone + Send + Sync + 'static,
56 ReqBody: rama_http_types::dep::http_body::Body<Data = Bytes, Error: Into<BoxError>>
57 + Send
58 + Sync
59 + 'static,
60 R: IntoResponse + Send + 'static,
61{
62 fn serve_http(
63 &self,
64 req: Request<ReqBody>,
65 ) -> impl Future<Output = Result<Response, Infallible>> + Send + 'static {
66 let RamaHttpService { svc, ctx } = self.clone();
67 async move {
68 let req = req.map(rama_http_types::Body::new);
69 Ok(svc.serve(ctx, req).await?.into_response())
70 }
71 }
72}
73
74#[derive(Debug, Default)]
75#[allow(dead_code)]
76pub(crate) struct VoidHttpService;
77
78impl<ReqBody> HttpService<ReqBody> for VoidHttpService
79where
80 ReqBody: rama_http_types::dep::http_body::Body<Data = Bytes, Error: Into<BoxError>>
81 + Send
82 + Sync
83 + 'static,
84{
85 #[allow(clippy::manual_async_fn)]
86 fn serve_http(
87 &self,
88 _req: Request<ReqBody>,
89 ) -> impl Future<Output = Result<Response, Infallible>> + Send + 'static {
90 async move { Ok(Response::new(rama_http_types::Body::empty())) }
91 }
92}
93
94mod sealed {
95 use super::*;
96
97 pub trait Sealed<T>: Send + Sync + 'static {}
98
99 impl<S, State, ReqBody, R> Sealed<ReqBody> for RamaHttpService<S, State>
100 where
101 S: Service<State, Request, Response = R, Error = Infallible> + Clone,
102 State: Clone + Send + Sync + 'static,
103 ReqBody: rama_http_types::dep::http_body::Body<Data = Bytes, Error: Into<BoxError>>
104 + Send
105 + Sync
106 + 'static,
107 R: IntoResponse + Send + 'static,
108 {
109 }
110
111 impl<ReqBody> Sealed<ReqBody> for VoidHttpService where
112 ReqBody: rama_http_types::dep::http_body::Body<Data = Bytes, Error: Into<BoxError>>
113 + Send
114 + Sync
115 + 'static
116 {
117 }
118}