camel_component_http/
registry.rs1use std::collections::HashMap;
2use std::path::PathBuf;
3use std::sync::Arc;
4
5use camel_component_api::CamelError;
6use tokio::sync::{RwLock, mpsc};
7use tower_http::services::ServeDir;
8
9use crate::RequestEnvelope;
10use crate::rest_match::RestEndpoint;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum MountMode {
16 Static,
17 Spa,
18}
19
20#[allow(dead_code)]
21pub struct StaticMount {
22 pub mount_path: String,
23 pub mode: MountMode,
24 pub dir: PathBuf,
25 pub cache_control: String,
26 pub error_pages: HashMap<u16, PathBuf>,
27 pub serve_dir: ServeDir,
28}
29
30impl std::fmt::Debug for StaticMount {
31 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32 f.debug_struct("StaticMount")
33 .field("mount_path", &self.mount_path)
34 .field("mode", &self.mode)
35 .field("dir", &self.dir)
36 .field("cache_control", &self.cache_control)
37 .field("error_pages", &self.error_pages)
38 .finish_non_exhaustive()
39 }
40}
41
42pub(crate) struct HttpRouteRegistryInner {
43 pub api_routes: HashMap<String, mpsc::Sender<RequestEnvelope>>,
47 pub rest_endpoints: Vec<RestEndpoint<mpsc::Sender<RequestEnvelope>>>,
52 pub mounts: Vec<StaticMount>,
53}
54
55impl std::fmt::Debug for HttpRouteRegistryInner {
56 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57 f.debug_struct("HttpRouteRegistryInner")
58 .field("api_routes", &self.api_routes.keys())
59 .field("rest_endpoints", &self.rest_endpoints.len())
60 .field("mounts", &self.mounts.len())
61 .finish()
62 }
63}
64
65#[derive(Clone)]
66pub struct HttpRouteRegistry {
67 pub(crate) inner: Arc<RwLock<HttpRouteRegistryInner>>,
68}
69
70impl std::fmt::Debug for HttpRouteRegistry {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 f.debug_struct("HttpRouteRegistry").finish_non_exhaustive()
73 }
74}
75
76impl Default for HttpRouteRegistry {
77 fn default() -> Self {
78 Self::new()
79 }
80}
81
82impl HttpRouteRegistry {
83 pub fn new() -> Self {
84 Self {
85 inner: Arc::new(RwLock::new(HttpRouteRegistryInner {
86 api_routes: HashMap::new(),
87 rest_endpoints: Vec::new(),
88 mounts: Vec::new(),
89 })),
90 }
91 }
92
93 pub async fn register_api_route(&self, path: String, sender: mpsc::Sender<RequestEnvelope>) {
94 let mut inner = self.inner.write().await;
95 inner.api_routes.insert(path, sender);
96 }
97
98 pub async fn unregister_api_route(&self, path: &str) {
99 let mut inner = self.inner.write().await;
100 inner.api_routes.remove(path);
101 }
102
103 pub async fn register_rest_endpoint(
108 &self,
109 method: String,
110 segments: Vec<crate::rest_match::PathSegment>,
111 sender: mpsc::Sender<RequestEnvelope>,
112 ) {
113 let mut inner = self.inner.write().await;
114 inner
117 .rest_endpoints
118 .retain(|ep| !(ep.method == method && ep.segments == segments));
119 inner.rest_endpoints.push(RestEndpoint {
120 method,
121 segments,
122 payload: sender,
123 });
124 }
125
126 pub async fn unregister_rest_endpoint(&self, method: &str, path_template: &str) {
133 let target_segments = crate::rest_match::parse_path_template(path_template);
134 let mut inner = self.inner.write().await;
135 inner.rest_endpoints.retain(|ep| {
136 !(ep.method == method && ep.segments == target_segments)
139 });
140 }
141
142 #[allow(dead_code)]
150 pub async fn register_static_mount(&self, mount: StaticMount) -> Result<(), CamelError> {
151 let mut inner = self.inner.write().await;
152 if inner
153 .mounts
154 .iter()
155 .any(|m| m.mount_path == mount.mount_path)
156 {
157 return Err(CamelError::Config(format!(
158 "duplicate static mount path '{}' on this port",
159 mount.mount_path
160 )));
161 }
162 inner.mounts.push(mount);
163 Ok(())
164 }
165
166 #[allow(dead_code)]
168 pub async fn unregister_static_mount(&self, mount_path: &str) {
169 let mut inner = self.inner.write().await;
170 inner.mounts.retain(|m| m.mount_path != mount_path);
171 }
172}