eve_rs/
middleware_handler.rs1use std::{fmt::Debug, marker::PhantomData};
2
3use regex::Regex;
4
5use crate::{Context, Middleware};
6
7pub(crate) struct MiddlewareHandler<TContext, TMiddleware, TErrorData>
8where
9 TContext: Context + Debug + Send + Sync,
10 TMiddleware: Middleware<TContext, TErrorData> + Clone + Send + Sync,
11 TErrorData: Default + Send + Sync,
12{
13 pub(crate) is_endpoint: bool,
14 pub(crate) mounted_url: String,
15 pub(crate) path_match: Regex,
16 pub(crate) handler: TMiddleware,
17 phantom_context: PhantomData<TContext>,
18 phantom_error: PhantomData<TErrorData>,
19}
20
21impl<TContext, TMiddleware, TErrorData> Clone
22 for MiddlewareHandler<TContext, TMiddleware, TErrorData>
23where
24 TContext: Context + Debug + Send + Sync,
25 TMiddleware: Middleware<TContext, TErrorData> + Clone + Send + Sync,
26 TErrorData: Default + Send + Sync,
27{
28 fn clone(&self) -> Self {
29 MiddlewareHandler {
30 is_endpoint: self.is_endpoint,
31 mounted_url: self.mounted_url.clone(),
32 path_match: self.path_match.clone(),
33 handler: self.handler.clone(),
34 phantom_context: PhantomData,
35 phantom_error: PhantomData,
36 }
37 }
38}
39
40impl<TContext, TMiddleware, TErrorData>
41 MiddlewareHandler<TContext, TMiddleware, TErrorData>
42where
43 TContext: Context + Debug + Send + Sync,
44 TMiddleware: Middleware<TContext, TErrorData> + Clone + Send + Sync,
45 TErrorData: Default + Send + Sync,
46{
47 pub(crate) fn new(
48 path: &str,
49 handler: TMiddleware,
50 is_endpoint: bool,
51 ) -> Self {
52 let mut mounted_url = path.to_string();
53
54 if mounted_url.starts_with("./") {
56 mounted_url = mounted_url[1..].to_string();
57 } else if !path.starts_with('/') {
58 mounted_url = format!("/{}", mounted_url);
59 }
60
61 if mounted_url.ends_with('/') {
63 mounted_url = path[..(path.len() - 1)].to_string();
64 }
65
66 if mounted_url.is_empty() {
68 mounted_url.push('/');
69 }
70
71 let mut regex_path = mounted_url
72 .replace('\\', "\\\\")
73 .replace('[', "\\[")
74 .replace(']', "\\]")
75 .replace('?', "\\?")
76 .replace('+', "\\+")
77 .replace('{', "\\{")
78 .replace('}', "\\}")
79 .replace('(', "\\(")
80 .replace(')', "\\)")
81 .replace('|', "\\|")
82 .replace('^', "\\^")
83 .replace('$', "\\$")
84 .replace('.', "\\.") .replace("**", "(.+)") .replace('*', "([^/]+)"); regex_path = Regex::new(":(?P<var>([a-zA-Z0-9_]+))")
92 .unwrap()
93 .replace_all(®ex_path, "(?P<$var>([^\\s/]+))")
95 .to_string();
96
97 if regex_path != "/" {
98 regex_path.push_str("[/]?");
102 }
103
104 if is_endpoint {
107 regex_path.push('$');
108 }
109
110 MiddlewareHandler {
111 is_endpoint,
112 mounted_url,
113 path_match: Regex::new(®ex_path).unwrap(),
114 handler,
115 phantom_context: PhantomData,
116 phantom_error: PhantomData,
117 }
118 }
119
120 pub(crate) fn is_match(&self, url: &str) -> bool {
121 self.path_match.is_match(url)
122 }
123}