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 tokio_util::sync::CancellationToken;
8use tower_http::services::ServeDir;
9
10use crate::RequestEnvelope;
11use crate::rest_match::RestEndpoint;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum MountMode {
17 Static,
18 Spa,
19}
20
21#[allow(dead_code)]
22pub struct StaticMount {
23 pub mount_path: String,
24 pub mode: MountMode,
25 pub dir: PathBuf,
26 pub cache_control: String,
27 pub error_pages: HashMap<u16, PathBuf>,
28 pub serve_dir: ServeDir,
29}
30
31impl std::fmt::Debug for StaticMount {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 f.debug_struct("StaticMount")
34 .field("mount_path", &self.mount_path)
35 .field("mode", &self.mode)
36 .field("dir", &self.dir)
37 .field("cache_control", &self.cache_control)
38 .field("error_pages", &self.error_pages)
39 .finish_non_exhaustive()
40 }
41}
42
43pub(crate) struct HttpRouteRegistryInner {
44 pub api_routes: HashMap<String, mpsc::Sender<RequestEnvelope>>,
48 pub rest_endpoints: Vec<RestEndpoint<mpsc::Sender<RequestEnvelope>>>,
53 pub mounts: Vec<StaticMount>,
54}
55
56impl std::fmt::Debug for HttpRouteRegistryInner {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 f.debug_struct("HttpRouteRegistryInner")
59 .field("api_routes", &self.api_routes.keys())
60 .field("rest_endpoints", &self.rest_endpoints.len())
61 .field("mounts", &self.mounts.len())
62 .finish()
63 }
64}
65
66#[derive(Clone)]
67pub struct HttpRouteRegistry {
68 pub(crate) inner: Arc<RwLock<HttpRouteRegistryInner>>,
69 pub(crate) server_exited: CancellationToken,
82}
83
84impl std::fmt::Debug for HttpRouteRegistry {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 f.debug_struct("HttpRouteRegistry").finish_non_exhaustive()
87 }
88}
89
90impl Default for HttpRouteRegistry {
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96impl HttpRouteRegistry {
97 pub fn new() -> Self {
98 Self::new_with_server_exited(CancellationToken::new())
99 }
100
101 pub(crate) fn new_with_server_exited(server_exited: CancellationToken) -> Self {
104 Self {
105 inner: Arc::new(RwLock::new(HttpRouteRegistryInner {
106 api_routes: HashMap::new(),
107 rest_endpoints: Vec::new(),
108 mounts: Vec::new(),
109 })),
110 server_exited,
111 }
112 }
113
114 pub async fn register_api_route(&self, path: String, sender: mpsc::Sender<RequestEnvelope>) {
115 let mut inner = self.inner.write().await;
116 inner.api_routes.insert(path, sender);
117 }
118
119 pub async fn unregister_api_route(&self, path: &str) {
120 let mut inner = self.inner.write().await;
121 inner.api_routes.remove(path);
122 }
123
124 pub async fn register_rest_endpoint(
129 &self,
130 method: String,
131 segments: Vec<crate::rest_match::PathSegment>,
132 sender: mpsc::Sender<RequestEnvelope>,
133 ) {
134 let mut inner = self.inner.write().await;
135 inner
138 .rest_endpoints
139 .retain(|ep| !(ep.method == method && ep.segments == segments));
140 inner.rest_endpoints.push(RestEndpoint {
141 method,
142 segments,
143 payload: sender,
144 });
145 }
146
147 pub async fn unregister_rest_endpoint(&self, method: &str, path_template: &str) {
154 let target_segments = crate::rest_match::parse_path_template(path_template);
155 let mut inner = self.inner.write().await;
156 inner.rest_endpoints.retain(|ep| {
157 !(ep.method == method && ep.segments == target_segments)
160 });
161 }
162
163 #[allow(dead_code)]
171 pub async fn register_static_mount(&self, mount: StaticMount) -> Result<(), CamelError> {
172 let mut inner = self.inner.write().await;
173 if inner
174 .mounts
175 .iter()
176 .any(|m| m.mount_path == mount.mount_path)
177 {
178 return Err(CamelError::Config(format!(
179 "duplicate static mount path '{}' on this port",
180 mount.mount_path
181 )));
182 }
183 inner.mounts.push(mount);
184 Ok(())
185 }
186
187 #[allow(dead_code)]
189 pub async fn unregister_static_mount(&self, mount_path: &str) {
190 let mut inner = self.inner.write().await;
191 inner.mounts.retain(|m| m.mount_path != mount_path);
192 }
193}