1pub mod cache;
2pub mod config;
3pub mod control;
4pub mod path_matcher;
5pub mod proxy;
6
7use axum::Router;
8use cache::{CacheStore, RefreshTrigger};
9use proxy::ProxyState;
10use std::sync::Arc;
11
12#[derive(Clone, Debug)]
14pub struct RequestInfo<'a> {
15 pub method: &'a str,
17 pub path: &'a str,
19 pub query: &'a str,
21 pub headers: &'a axum::http::HeaderMap,
23}
24
25#[derive(Clone)]
27pub struct CreateProxyConfig {
28 pub proxy_url: String,
30
31 pub include_paths: Vec<String>,
34
35 pub exclude_paths: Vec<String>,
39
40 pub cache_key_fn: Arc<dyn Fn(&RequestInfo) -> String + Send + Sync>,
44}
45
46impl CreateProxyConfig {
47 pub fn new(proxy_url: String) -> Self {
49 Self {
50 proxy_url,
51 include_paths: vec![],
52 exclude_paths: vec![],
53 cache_key_fn: Arc::new(|req_info| {
54 if req_info.query.is_empty() {
55 format!("{}:{}", req_info.method, req_info.path)
56 } else {
57 format!("{}:{}?{}", req_info.method, req_info.path, req_info.query)
58 }
59 }),
60 }
61 }
62
63 pub fn with_include_paths(mut self, paths: Vec<String>) -> Self {
65 self.include_paths = paths;
66 self
67 }
68
69 pub fn with_exclude_paths(mut self, paths: Vec<String>) -> Self {
71 self.exclude_paths = paths;
72 self
73 }
74
75 pub fn with_cache_key_fn<F>(mut self, f: F) -> Self
77 where
78 F: Fn(&RequestInfo) -> String + Send + Sync + 'static,
79 {
80 self.cache_key_fn = Arc::new(f);
81 self
82 }
83}
84
85pub fn create_proxy(config: CreateProxyConfig) -> (Router, RefreshTrigger) {
88 let refresh_trigger = RefreshTrigger::new();
89 let cache = CacheStore::new(refresh_trigger.clone());
90
91 let proxy_state = Arc::new(ProxyState::new(cache, config));
92
93 let app = Router::new()
94 .fallback(proxy::proxy_handler)
95 .with_state(proxy_state);
96
97 (app, refresh_trigger)
98}
99
100pub fn create_proxy_with_trigger(config: CreateProxyConfig, refresh_trigger: RefreshTrigger) -> Router {
102 let cache = CacheStore::new(refresh_trigger);
103 let proxy_state = Arc::new(ProxyState::new(cache, config));
104
105 Router::new()
106 .fallback(proxy::proxy_handler)
107 .with_state(proxy_state)
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn test_create_proxy() {
116 let config = CreateProxyConfig::new("http://localhost:8080".to_string());
117 let (_app, trigger) = create_proxy(config);
118 trigger.trigger();
119 }
121}