httpward_core/httpward_middleware/
pipe.rs1use std::os::raw::c_void;
4use std::sync::Arc;
5use crate::httpward_middleware::middleware_trait::HttpWardMiddleware;
6use crate::httpward_middleware::next::Next;
7use crate::httpward_middleware::types::BoxError;
8use rama::http::{Body, Request, Response};
9use rama::Context;
10use rama::service::Service;
11use std::fmt;
12
13type BoxedMiddleware = Arc<dyn HttpWardMiddleware>;
16
17#[derive(Clone)]
20pub struct HttpWardMiddlewarePipe {
21 inner: Arc<Vec<BoxedMiddleware>>,
22}
23
24impl Default for HttpWardMiddlewarePipe {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl fmt::Debug for HttpWardMiddlewarePipe {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 f.debug_struct("HttpWardMiddlewarePipe")
33 .field("middleware_count", &self.inner.len())
34 .finish()
35 }
36}
37
38impl HttpWardMiddlewarePipe {
39 pub fn new() -> Self {
41 Self {
42 inner: Arc::new(Vec::new()),
43 }
44 }
45
46 pub fn len(&self) -> usize {
48 self.inner.len()
49 }
50
51 pub fn is_empty(&self) -> bool {
52 self.inner.is_empty()
53 }
54
55 pub fn add_layer<M>(&self, mw: M) -> Self
57 where
58 M: HttpWardMiddleware + Send + Sync + 'static,
59 {
60 let mut new_vec = (*self.inner).clone();
61 new_vec.push(Arc::new(mw));
62 Self {
63 inner: Arc::new(new_vec),
64 }
65 }
66
67 pub fn add_boxed_layer(&self, mw: BoxedMiddleware) -> Self {
70 let mut new_vec = (*self.inner).clone();
72 new_vec.push(mw);
73 Self {
74 inner: Arc::new(new_vec),
75 }
76 }
77
78 pub fn get_layer_by_name(
81 &self,
82 name: &str,
83 ) -> Option<&BoxedMiddleware> {
84 self.inner.iter().find(|m| m.name().map_or(false, |n| n == name))
85 }
86
87 pub async fn execute_middleware<S>(
93 &self,
94 inner: S,
95 ctx: Context<()>,
96 req: Request<Body>,
97 ) -> Result<Response<Body>, BoxError>
98 where
99 S: Service<(), Request<Body>, Response = Response<Body>> + Clone + Send + Sync + 'static,
100 S::Error: std::error::Error + Send + Sync + 'static,
101 {
102 let slice: &[BoxedMiddleware] = &*self.inner;
103
104 let boxed_service = crate::httpward_middleware::adapter::box_service_from(inner);
106
107 let next = Next::new(slice, &boxed_service);
108
109 next.run(ctx, req).await
110 }
111}
112
113pub struct HttpWardMiddlewarePipeBuilder {
116 v: Vec<BoxedMiddleware>,
117}
118
119impl HttpWardMiddlewarePipeBuilder {
120 pub fn new() -> Self {
122 Self { v: Vec::new() }
123 }
124
125 pub fn add_layer<M>(mut self, mw: M) -> Self
128 where
129 M: HttpWardMiddleware + Send + Sync + 'static,
130 {
131 self.v.push(Arc::new(mw));
132 self
133 }
134
135 pub fn push_box(mut self, mw: BoxedMiddleware) -> Self {
137 self.v.push(mw);
138 self
139 }
140
141 pub fn build(self) -> HttpWardMiddlewarePipe {
143 HttpWardMiddlewarePipe {
144 inner: Arc::new(self.v),
145 }
146 }
147}
148
149#[repr(C)]
151pub struct MiddlewareFatPtr {
152 pub data: *mut c_void,
153 pub vtable: *mut c_void,
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159 use async_trait::async_trait;
160 use rama::http::{Body, Request, Response};
161 use rama::Context;
162 use crate::httpward_middleware::types::BoxError;
163 use crate::httpward_middleware::next::Next;
164
165 struct DummyMw;
167 #[async_trait]
168 impl HttpWardMiddleware for DummyMw {
169 async fn handle(&self, ctx: Context<()>, req: Request<Body>, next: Next<'_>) -> Result<Response<Body>, BoxError> {
170 next.run(ctx, req).await
172 }
173 }
174
175 #[tokio::test]
176 async fn build_and_execute_pipe() {
177 let builder = HttpWardMiddlewarePipeBuilder::new()
179 .add_layer(DummyMw);
180 let pipe = builder.build();
181
182 assert_eq!(pipe.len(), 1);
184 assert!(!pipe.is_empty());
185 }
186}