httpward_core/
middleware_config_ext.rs1use crate::config::strategy::MiddlewareConfig;
2use crate::core::HttpWardContext;
3use rama::Context;
4use rama::http::{Request, Body};
5use serde::de::DeserializeOwned;
6use std::error::Error;
7
8pub trait MiddlewareConfigExt {
10 fn get_middleware_config(&self, middleware_name: &str) -> Result<Option<MiddlewareConfig>, Box<dyn Error + Send + Sync>>;
12
13 fn get_middleware_config_typed<T>(&self, middleware_name: &str) -> Result<Option<T>, Box<dyn Error + Send + Sync>>
15 where
16 T: DeserializeOwned;
17
18 fn get_middleware_config_for_path(&self, path: &str, middleware_name: &str) -> Result<Option<MiddlewareConfig>, Box<dyn Error + Send + Sync>>;
20
21 fn get_middleware_config_for_path_typed<T>(&self, path: &str, middleware_name: &str) -> Result<Option<T>, Box<dyn Error + Send + Sync>>
23 where
24 T: DeserializeOwned;
25}
26
27impl MiddlewareConfigExt for Context<()> {
28 fn get_middleware_config(&self, middleware_name: &str) -> Result<Option<MiddlewareConfig>, Box<dyn Error + Send + Sync>> {
29 let httpward_ctx = self.get::<HttpWardContext>()
30 .ok_or("HttpWardContext not found")?;
31
32 if let Some((path, _)) = self.get::<(String, ())>() {
34 if let Some(site) = &httpward_ctx.current_site {
36 site.get_active_strategy_config_by_route(&path, middleware_name)
37 .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
38 } else {
39 Err("No current site".into())
40 }
41 } else {
42 Err("No path information available in context".into())
44 }
45 }
46
47 fn get_middleware_config_typed<T>(&self, middleware_name: &str) -> Result<Option<T>, Box<dyn Error + Send + Sync>>
48 where
49 T: DeserializeOwned,
50 {
51 if let Some(config) = self.get_middleware_config(middleware_name)? {
52 let typed_config: T = config.config_into()?;
53 Ok(Some(typed_config))
54 } else {
55 Ok(None)
56 }
57 }
58
59 fn get_middleware_config_for_path(&self, path: &str, middleware_name: &str) -> Result<Option<MiddlewareConfig>, Box<dyn Error + Send + Sync>> {
60 let httpward_ctx = self.get::<HttpWardContext>()
61 .ok_or("HttpWardContext not found")?;
62
63 if let Some(site) = &httpward_ctx.current_site {
64 site.get_active_strategy_config_by_route(path, middleware_name)
65 .map_err(|e| Box::new(e) as Box<dyn Error + Send + Sync>)
66 } else {
67 Err("No current site".into())
68 }
69 }
70
71 fn get_middleware_config_for_path_typed<T>(&self, path: &str, middleware_name: &str) -> Result<Option<T>, Box<dyn Error + Send + Sync>>
72 where
73 T: DeserializeOwned,
74 {
75 if let Some(config) = self.get_middleware_config_for_path(path, middleware_name)? {
76 let typed_config: T = config.config_into()?;
77 Ok(Some(typed_config))
78 } else {
79 Ok(None)
80 }
81 }
82}
83
84pub fn get_config_from_ctx<T>(
87 ctx: &Context<()>,
88 req: &Request<Body>,
89 middleware_name: &str,
90) -> Result<T, Box<dyn Error + Send + Sync>>
91where
92 T: DeserializeOwned,
93{
94 let path = req.uri().path();
95 ctx.get_middleware_config_for_path_typed::<T>(path, middleware_name)?
96 .ok_or_else(|| format!("No configuration found for middleware '{}' on path '{}'", middleware_name, path).into())
97}
98
99pub fn get_config_from_ctx_for_module<T>(
102 ctx: &Context<()>,
103 req: &Request<Body>,
104 module_name: &str,
105) -> Result<T, Box<dyn Error + Send + Sync>>
106where
107 T: DeserializeOwned,
108{
109 get_config_from_ctx::<T>(ctx, req, module_name)
110}
111
112#[macro_export]
115macro_rules! get_config_from_current_module {
116 ($config_type:ty, $ctx:expr, $req:expr) => {
117 $crate::middleware_config_ext::get_config_from_ctx_for_module::<$config_type>(
118 $ctx,
119 $req,
120 module_path!().split("::").last().unwrap_or("unknown")
121 )
122 };
123}
124
125#[macro_export]
128macro_rules! get_module_config_from_current_crate {
129 ($config_type:ty, $ctx:expr, $req:expr) => {
130 $crate::middleware_config_ext::get_config_from_ctx_for_module::<$config_type>(
131 $ctx,
132 $req,
133 env!("CARGO_PKG_NAME")
134 )
135 };
136}
137
138pub fn get_middleware_config_from_ctx(
140 ctx: &Context<()>,
141 middleware_name: &str,
142) -> Result<Option<MiddlewareConfig>, Box<dyn Error + Send + Sync>> {
143 ctx.get_middleware_config(middleware_name)
144}
145
146pub fn get_middleware_config_typed_from_ctx<T>(
148 ctx: &Context<()>,
149 middleware_name: &str,
150) -> Result<Option<T>, Box<dyn Error + Send + Sync>>
151where
152 T: DeserializeOwned,
153{
154 ctx.get_middleware_config_typed(middleware_name)
155}