1mod compile;
2mod path;
3
4pub use path::{join_paths, normalize_path, to_brace_path};
5pub(crate) use compile::{compile_router, CompiledRouter};
6pub(crate) use path::to_matchit_path;
7
8use path::normalize_prefix;
9
10use crate::handler::{ErrorHandlerFn, FallibleHandler, IntoHandler};
11use crate::middleware::{IntoMwEntry, MwEntry};
12use crate::raw::{IntoRawHandler, RawHandler};
13use crate::response::Response;
14use crate::route_value::{MetaMap, RouteValue};
15use crate::state::TypeMap;
16use http::Method;
17use std::collections::HashMap;
18use std::sync::Arc;
19
20struct RouteDef {
21 method: Method,
22 path: String,
24 middleware: Vec<MwEntry>,
25 handler: FallibleHandler,
26 meta: MetaMap,
27}
28
29struct RawDef {
30 path: String,
31 handler: RawHandler,
32}
33
34#[derive(Clone)]
36pub enum RouteEntry {
37 Http {
38 method: Method,
39 path: String,
40 meta: MetaMap,
42 },
43 Raw {
44 path: String,
45 },
46}
47
48#[derive(Clone)]
50pub struct RouteTable(pub Vec<RouteEntry>);
51
52pub(crate) type CatcherMap = HashMap<u16, FallibleHandler>;
54
55pub struct Router {
57 routes: Vec<RouteDef>,
58 raw_routes: Vec<RawDef>,
59 middleware: Vec<MwEntry>,
60 pub(crate) state: TypeMap,
61 pub(crate) defaults: MetaMap,
63 last_was_route: bool,
65 catchers: CatcherMap,
67 scoped_catchers: Vec<(String, CatcherMap)>,
69 error_handler: Option<ErrorHandlerFn>,
70}
71
72impl Router {
73 pub fn new() -> Self {
74 Self {
75 routes: Vec::new(),
76 raw_routes: Vec::new(),
77 middleware: Vec::new(),
78 state: TypeMap::new(),
79 defaults: MetaMap::new(),
80 last_was_route: false,
81 catchers: HashMap::new(),
82 scoped_catchers: Vec::new(),
83 error_handler: None,
84 }
85 }
86
87 pub(crate) fn clone_for_compile(&self) -> Router {
89 Router {
90 routes: self
91 .routes
92 .iter()
93 .map(|r| RouteDef {
94 method: r.method.clone(),
95 path: r.path.clone(),
96 middleware: r.middleware.clone(),
97 handler: Arc::clone(&r.handler),
98 meta: r.meta.clone(),
99 })
100 .collect(),
101 raw_routes: self
102 .raw_routes
103 .iter()
104 .map(|r| RawDef {
105 path: r.path.clone(),
106 handler: Arc::clone(&r.handler),
107 })
108 .collect(),
109 middleware: self.middleware.clone(),
110 state: self.state.clone_map(),
111 defaults: self.defaults.clone(),
112 last_was_route: self.last_was_route,
113 catchers: self
114 .catchers
115 .iter()
116 .map(|(s, h)| (*s, Arc::clone(h)))
117 .collect(),
118 scoped_catchers: self
119 .scoped_catchers
120 .iter()
121 .map(|(p, m)| {
122 (
123 p.clone(),
124 m.iter().map(|(s, h)| (*s, Arc::clone(h))).collect(),
125 )
126 })
127 .collect(),
128 error_handler: self.error_handler.as_ref().map(Arc::clone),
129 }
130 }
131
132 pub fn use_middleware<M>(&mut self, mw: M) -> &mut Self
133 where
134 M: IntoMwEntry,
135 {
136 self.last_was_route = false;
137 self.middleware.push(mw.into_mw_entry());
138 self
139 }
140
141 pub fn with<T: RouteValue>(&mut self, value: T) -> &mut Self {
146 if self.last_was_route {
147 if let Some(r) = self.routes.last_mut() {
148 r.meta.insert(value);
149 }
150 } else {
151 self.defaults.insert(value);
152 }
153 self
154 }
155
156 pub fn with_update<T, F>(&mut self, f: F) -> &mut Self
158 where
159 T: RouteValue + Clone + Default,
160 F: FnOnce(&mut T),
161 {
162 if let Some(r) = self.routes.last_mut() {
163 let mut v = r.meta.get::<T>().map(|a| (*a).clone()).unwrap_or_default();
164 f(&mut v);
165 r.meta.insert(v);
166 self.last_was_route = true;
167 }
168 self
169 }
170
171 pub fn route_middleware<M>(&mut self, mw: M) -> &mut Self
173 where
174 M: IntoMwEntry,
175 {
176 if let Some(r) = self.routes.last_mut() {
177 let entry = mw.into_mw_entry();
178 if !r.middleware.iter().any(|e| e.name == entry.name) {
179 r.middleware.push(entry);
180 }
181 }
182 self
183 }
184
185 pub fn route_meta<T: RouteValue>(&mut self, value: T) -> &mut Self {
187 if let Some(r) = self.routes.last_mut() {
188 r.meta.insert(value);
189 self.last_was_route = true;
190 } else {
191 self.defaults.insert(value);
192 }
193 self
194 }
195
196 pub fn state<T>(&mut self, value: T) -> &mut Self
197 where
198 T: Send + Sync + 'static,
199 {
200 self.state.insert(value);
201 self
202 }
203
204 pub fn try_state<T>(&self) -> Option<std::sync::Arc<T>>
206 where
207 T: Send + Sync + 'static,
208 {
209 self.state.get::<T>()
210 }
211
212 pub fn get<H, T>(&mut self, path: &str, handler: H) -> &mut Self
213 where
214 H: IntoHandler<T>,
215 {
216 self.add(Method::GET, path, handler)
217 }
218
219 pub fn post<H, T>(&mut self, path: &str, handler: H) -> &mut Self
220 where
221 H: IntoHandler<T>,
222 {
223 self.add(Method::POST, path, handler)
224 }
225
226 pub fn put<H, T>(&mut self, path: &str, handler: H) -> &mut Self
227 where
228 H: IntoHandler<T>,
229 {
230 self.add(Method::PUT, path, handler)
231 }
232
233 pub fn patch<H, T>(&mut self, path: &str, handler: H) -> &mut Self
234 where
235 H: IntoHandler<T>,
236 {
237 self.add(Method::PATCH, path, handler)
238 }
239
240 pub fn delete<H, T>(&mut self, path: &str, handler: H) -> &mut Self
241 where
242 H: IntoHandler<T>,
243 {
244 self.add(Method::DELETE, path, handler)
245 }
246
247 pub fn head<H, T>(&mut self, path: &str, handler: H) -> &mut Self
249 where
250 H: IntoHandler<T>,
251 {
252 self.add(Method::HEAD, path, handler)
253 }
254
255 pub fn options<H, T>(&mut self, path: &str, handler: H) -> &mut Self
257 where
258 H: IntoHandler<T>,
259 {
260 self.add(Method::OPTIONS, path, handler)
261 }
262
263 pub fn redirect(&mut self, from: &str, to: impl Into<String>, status: u16) -> &mut Self {
270 let location = to.into();
271 self.get(from, move || {
272 let location = location.clone();
273 async move { crate::Redirect::with(status, location) }
274 })
275 }
276
277 pub fn raw<H>(&mut self, path: &str, handler: H) -> &mut Self
279 where
280 H: IntoRawHandler,
281 {
282 self.raw_routes.push(RawDef {
283 path: normalize_path(path),
284 handler: handler.into_raw_handler(),
285 });
286 self
287 }
288
289 pub fn mount(&mut self, prefix: &str, other: Router) -> &mut Self {
295 let prefix = normalize_prefix(prefix);
296 let child_mw = other.middleware;
297
298 for mut route in other.routes {
299 route.path = join_paths(&prefix, &route.path);
300 let mut mw = child_mw.clone();
301 mw.extend(route.middleware);
302 route.middleware = mw;
303 let mut meta = other.defaults.clone();
304 meta.extend(route.meta);
305 route.meta = meta;
306 self.routes.push(route);
307 }
308 self.last_was_route = false;
309
310 for mut raw in other.raw_routes {
311 raw.path = join_paths(&prefix, &raw.path);
312 self.raw_routes.push(raw);
313 }
314
315 self.state.extend(other.state);
316
317 if !other.catchers.is_empty() {
318 self.scoped_catchers.push((prefix.clone(), other.catchers));
319 }
320 for (child_prefix, map) in other.scoped_catchers {
321 self.scoped_catchers
322 .push((join_paths(&prefix, &child_prefix), map));
323 }
324 if self.error_handler.is_none() {
325 self.error_handler = other.error_handler;
326 }
327
328 self
329 }
330
331 pub fn group<F>(&mut self, prefix: &str, f: F) -> &mut Self
333 where
334 F: FnOnce(&mut Router),
335 {
336 let mut child = Router::new();
337 f(&mut child);
338 self.mount(prefix, child)
339 }
340
341 pub fn catch<H, T>(&mut self, status: u16, handler: H) -> &mut Self
346 where
347 H: IntoHandler<T>,
348 {
349 self.last_was_route = false;
350 self.catchers.insert(status, handler.into_handler());
351 self
352 }
353
354 pub fn not_found<H, T>(&mut self, handler: H) -> &mut Self
356 where
357 H: IntoHandler<T>,
358 {
359 self.catch(404, handler)
360 }
361
362 pub fn error_handler<F, Fut>(&mut self, f: F) -> &mut Self
364 where
365 F: Fn(crate::error::Error) -> Fut + Send + Sync + 'static,
366 Fut: std::future::Future<Output = Response> + Send + 'static,
367 {
368 self.error_handler = Some(Arc::new(move |err| Box::pin(f(err))));
369 self
370 }
371
372 pub fn route_entries(&self) -> Vec<RouteEntry> {
374 let mut out = Vec::new();
375 for r in &self.routes {
376 let mut meta = self.defaults.clone();
377 meta.extend(r.meta.clone());
378 out.push(RouteEntry::Http {
379 method: r.method.clone(),
380 path: r.path.clone(),
381 meta,
382 });
383 }
384 for r in &self.raw_routes {
385 out.push(RouteEntry::Raw {
386 path: r.path.clone(),
387 });
388 }
389 out
390 }
391
392 pub(crate) fn check_route_values(
394 &self,
395 state: &crate::state::StateMap,
396 installed_plugins: &std::collections::HashSet<&'static str>,
397 ) -> Result<(), String> {
398 use crate::route_value::BuildCtx;
399 let ctx = BuildCtx {
400 state,
401 installed_plugins,
402 route_path: "<defaults>",
403 route_method: None,
404 };
405 self.defaults.check_all(&ctx)?;
406 for r in &self.routes {
407 let mut meta = self.defaults.clone();
408 meta.extend(r.meta.clone());
409 let ctx = BuildCtx {
410 state,
411 installed_plugins,
412 route_path: &r.path,
413 route_method: Some(&r.method),
414 };
415 meta.check_all(&ctx)?;
416 }
417 Ok(())
418 }
419
420 pub fn explain(&self) -> String {
422 use std::fmt::Write;
423 let mut out = String::new();
424 let _ = writeln!(out, "root_middleware: [{}]", format_mw_names(&self.middleware));
425 let _ = writeln!(out, "error_handler: {}", self.error_handler.is_some());
426 let mut catch_lines = Vec::new();
427 if !self.catchers.is_empty() {
428 let mut codes: Vec<_> = self.catchers.keys().copied().collect();
429 codes.sort_unstable();
430 catch_lines.push(format!("/ → {:?}", codes));
431 }
432 for (prefix, map) in &self.scoped_catchers {
433 let mut codes: Vec<_> = map.keys().copied().collect();
434 codes.sort_unstable();
435 let p = if prefix.is_empty() { "/" } else { prefix.as_str() };
436 catch_lines.push(format!("{p} → {:?}", codes));
437 }
438 let _ = writeln!(out, "catchers: [{}]", catch_lines.join("; "));
439 if !self.defaults.is_empty() {
440 let _ = writeln!(out, "defaults: [{}]", self.defaults.labels().join(" "));
441 }
442 for r in &self.routes {
443 let labels = r.meta.labels();
444 if labels.is_empty() {
445 let _ = writeln!(
446 out,
447 "{} {} mw=[{}]",
448 r.method,
449 r.path,
450 format_mw_names(&r.middleware)
451 );
452 } else {
453 let _ = writeln!(
454 out,
455 "{} {} mw=[{}] {}",
456 r.method,
457 r.path,
458 format_mw_names(&r.middleware),
459 labels.join(" ")
460 );
461 }
462 }
463 for r in &self.raw_routes {
464 let _ = writeln!(out, "RAW {} mw=[]", r.path);
465 }
466 out
467 }
468
469 fn add<H, T>(&mut self, method: Method, path: &str, handler: H) -> &mut Self
470 where
471 H: IntoHandler<T>,
472 {
473 self.routes.push(RouteDef {
474 method,
475 path: normalize_path(path),
476 middleware: Vec::new(),
478 handler: handler.into_handler(),
479 meta: MetaMap::new(),
480 });
481 self.last_was_route = true;
482 self
483 }
484}
485
486impl Default for Router {
487 fn default() -> Self {
488 Self::new()
489 }
490}
491
492fn format_mw_names(entries: &[MwEntry]) -> String {
493 entries
494 .iter()
495 .map(|e| e.name.as_str())
496 .collect::<Vec<_>>()
497 .join(", ")
498}