credence_lib/configuration/
urls.rs

1use super::{
2    super::{resolve::*, util::*},
3    protect::*,
4    redirect::*,
5};
6
7use {axum::http::*, compris::resolve::*, kutil::cli::depict::*, regex::*};
8
9//
10// UrlsConfiguration
11//
12
13/// URLs configuration.
14#[derive(Clone, Debug, Depict, Resolve)]
15pub struct UrlsConfiguration {
16    /// Hide.
17    #[resolve(key = "hide")]
18    #[depict(iter(item), as(display), style(string))]
19    pub hide: Vec<ResolveRegex>,
20
21    /// Redirect trailing slashes.
22    #[resolve(key = "redirect-trailing-slashes")]
23    #[depict(style(symbol))]
24    pub redirect_trailing_slashes: bool,
25
26    /// Redirect.
27    #[resolve]
28    #[depict(iter(item), as(depict))]
29    pub redirect: Vec<Redirect>,
30
31    /// Protect.
32    #[resolve]
33    #[depict(iter(item), as(depict))]
34    pub protect: Vec<Protect>,
35}
36
37impl UrlsConfiguration {
38    /// If the URI path is redirected returns the redirected URI.
39    pub fn redirect(&self, uri_path: &str) -> Option<(String, StatusCode)> {
40        match self.has_trailing_slashes(uri_path) {
41            Some(uri_path) => Some((uri_path.into(), StatusCode::MOVED_PERMANENTLY)),
42
43            None => {
44                for redirect in &self.redirect {
45                    if let Some(uri_path) = redirect.redirect(uri_path) {
46                        return Some(uri_path);
47                    }
48                }
49
50                return None;
51            }
52        }
53    }
54
55    /// If `redirect_trailing_slashes` is true and the URI has trailing slashes returns it without
56    /// them.
57    pub fn has_trailing_slashes<'path>(&self, uri_path: &'path str) -> Option<&'path str> {
58        if self.redirect_trailing_slashes && (uri_path.len() > 1) && uri_path.ends_with(PATH_SEPARATOR) {
59            Some(uri_path.trim_end_matches(PATH_SEPARATOR))
60        } else {
61            None
62        }
63    }
64
65    /// If the URI is protected returns the [Protect].
66    pub fn protect(&self, uri_path: &str) -> Option<&Protect> {
67        for protect in &self.protect {
68            if protect.protect(uri_path) {
69                return Some(protect);
70            }
71        }
72
73        None
74    }
75}
76
77impl Default for UrlsConfiguration {
78    fn default() -> Self {
79        Self {
80            hide: vec![Regex::new(r"\.html$").expect("regex").into()],
81            redirect_trailing_slashes: true,
82            redirect: Default::default(),
83            protect: Default::default(),
84        }
85    }
86}