awpak_rs/services/middleware/
middleware.rs1use std::sync::OnceLock;
2
3use crate::io::io::IO;
4
5pub enum MiddlewareResponse
10{
11 Next( IO ),
15
16 Cancel( IO )
20}
21
22pub type MiddlewareResponseType = std::pin::Pin<std::boxed::Box<
23 dyn std::future::Future<
24 Output = MiddlewareResponse
25 >
26 + std::marker::Send
27 >>;
28
29#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
30pub enum MiddlewareExecOrder
31{
32 PRE,
33 POST
34}
35
36#[derive(Copy, Clone)]
37pub struct Middleware
38{
39 pub regex : Option<&'static str>,
40 pub order : usize,
41 pub method : Option<&'static str>,
42 pub fnc : fn( IO ) -> MiddlewareResponseType,
43 pub exec_order : MiddlewareExecOrder
44}
45
46impl Middleware
47{
48 pub const fn new(
49 regex : Option<&'static str>,
50 order : usize,
51 method : Option<&'static str>,
52 fnc : fn( IO ) -> MiddlewareResponseType,
53 exec_order : MiddlewareExecOrder
54 ) -> Self
55 {
56 Self
57 {
58 regex,
59 order,
60 method,
61 fnc,
62 exec_order
63 }
64 }
65}
66
67inventory::collect!( Middleware );
68
69fn pre_middlewares() -> &'static Vec<Middleware> {
70 static ARRAY_PRE_MIDDLEWARES: OnceLock<Vec<Middleware>> = OnceLock::new();
71 ARRAY_PRE_MIDDLEWARES.get_or_init(|| get_init_middlewares( MiddlewareExecOrder::PRE ) )
72}
73
74fn post_middlewares() -> &'static Vec<Middleware> {
75 static ARRAY_POST_MIDDLEWARES: OnceLock<Vec<Middleware>> = OnceLock::new();
76 ARRAY_POST_MIDDLEWARES.get_or_init(|| get_init_middlewares( MiddlewareExecOrder::POST ) )
77}
78
79pub fn initialize_middlewares()
80{
81 let _ = pre_middlewares();
82 let _ = post_middlewares();
83}
84
85fn get_init_middlewares( exec_order : MiddlewareExecOrder ) -> Vec<Middleware>
86{
87 let mut middlewares : Vec<Middleware> = vec![];
88
89 for m in inventory::iter::<Middleware>
90 {
91 if m.exec_order == exec_order
92 {
93 middlewares.push( *m );
94 }
95 }
96
97 middlewares.sort_by( | a, b | a.order.cmp( &b.order ) );
98
99 middlewares
100}
101
102pub async fn pre_middlewares_exec( io : IO ) -> MiddlewareResponse
103{
104 exec_middlewares( io, MiddlewareExecOrder::PRE ).await
105}
106
107pub async fn post_middlewares_exec( io : IO ) -> MiddlewareResponse
108{
109 exec_middlewares( io, MiddlewareExecOrder::POST ).await
110}
111
112async fn exec_middlewares( mut io : IO, exec_order : MiddlewareExecOrder ) -> MiddlewareResponse
113{
114 let middlewares = match exec_order
115 {
116 MiddlewareExecOrder::POST => post_middlewares(),
117 MiddlewareExecOrder::PRE => pre_middlewares()
118 };
119
120 for middleware in middlewares
121 {
122 if middleware.method.is_some()
123 {
124 if &io.request.method.to_lowercase().as_str() != middleware.method.as_ref().unwrap()
125 {
126 continue;
127 }
128 }
129
130 if middleware.regex.is_some()
131 {
132 match regex::Regex::new( middleware.regex.as_ref().unwrap() ) {
133
134 Ok( v ) =>
135 if v.is_match( &io.request.uri.path ) {} else { continue; },
136 _ => { continue; }
137 };
138 }
139
140 io = match ( middleware.fnc )( io ).await {
141 MiddlewareResponse::Next( v ) => v,
142 MiddlewareResponse::Cancel( v ) => return MiddlewareResponse::Cancel( v )
143 };
144 }
145
146 MiddlewareResponse::Next( io )
147}