credence_lib/configuration/
credence.rs1use super::{
2 super::{middleware::*, util::*},
3 caching::*,
4 encoding::*,
5 error::*,
6 files::*,
7 port::*,
8 render::*,
9 requests::*,
10 urls::*,
11};
12
13use {
14 compris::{normal::*, parse::*, resolve::*, *},
15 kutil_cli::debug::*,
16 kutil_http::{
17 cache::{Cache, CommonCacheKey},
18 tower::caching::*,
19 *,
20 },
21 std::{collections::*, io, path::*},
22};
23
24#[derive(Clone, Debug, Debuggable, Resolve)]
30pub struct CredenceConfiguration {
31 #[resolve]
33 #[debuggable(skip)]
34 pub definitions: Option<Value>,
35
36 #[resolve]
38 #[debuggable(as(debuggable))]
39 pub files: FilesConfiguration,
40
41 #[resolve]
43 #[debuggable(iter(kv), key_style(number), as(debuggable))]
44 pub ports: BTreeMap<u16, Port>,
45
46 #[resolve]
48 #[debuggable(as(debuggable))]
49 pub requests: RequestsConfiguration,
50
51 #[resolve]
53 #[debuggable(as(debuggable))]
54 pub urls: UrlsConfiguration,
55
56 #[resolve]
58 #[debuggable(as(debuggable))]
59 pub render: RenderConfiguration,
60
61 #[resolve]
63 #[debuggable(as(debuggable))]
64 pub caching: CachingConfiguration,
65
66 #[resolve]
68 #[debuggable(as(debuggable))]
69 pub encoding: EncodingConfiguration,
70}
71
72impl CredenceConfiguration {
73 pub fn read<ReadT>(reader: &mut ReadT) -> io::Result<Self>
75 where
76 ReadT: io::Read,
77 {
78 let value =
79 Parser::new(Format::YAML).with_try_unsigned_integers(true).parse(reader).map_err(io::Error::other)?;
80
81 <Value as Resolve<_, CommonResolveContext, CommonResolveError>>::resolve(&value)
82 .map_err(io::Error::other)?
83 .ok_or(io::Error::other("no configuration"))
84 }
85
86 pub fn validate<PathT>(&mut self, base_path: PathT) -> Result<(), ConfigurationError>
88 where
89 PathT: AsRef<Path>,
90 {
91 for port in &mut self.ports.values_mut() {
92 port.validate(&base_path)?;
93 }
94
95 self.files.validate(base_path)
96 }
97
98 pub fn caching_layer<RequestBodyT, CacheT>(
100 &self,
101 cache: CacheT,
102 ) -> CachingLayer<RequestBodyT, CacheT, CommonCacheKey>
103 where
104 CacheT: Cache<CommonCacheKey>,
105 {
106 let skip_media_types = self.encoding.skip_media_types();
108
109 CachingLayer::new()
110 .cache(cache.clone())
111 .cacheable_by_default(self.caching.default)
112 .cache_key(|context| {
113 if let Some(socket) = context.request.extensions().get::<Socket>() {
114 context.cache_key.host = Some(socket.host.clone());
115 }
116 })
117 .min_cacheable_body_size(self.caching.min_body_size.value.into())
118 .max_cacheable_body_size(self.caching.max_body_size.value.into())
119 .min_encodable_body_size(self.encoding.min_body_size.value.into())
120 .encodable_by_default(self.encoding.default)
121 .encodable_by_response(move |context| match context.headers.content_type() {
122 Some(content_type) => !skip_media_types.contains(&content_type),
123 None => true,
124 })
125 }
126
127 pub fn hide(&self, uri_path: &str) -> bool {
129 if uri_path_has_hidden_segment(uri_path) {
130 return true;
131 }
132
133 for hide in &self.urls.hide {
134 if hide.value.is_match(uri_path) {
135 return true;
136 }
137 }
138
139 self.render.is_rendered_page(uri_path).is_some()
140 }
141
142 pub fn rendered_page_uri_path(&self, uri_path: &str) -> io::Result<Option<String>> {
146 let asset_path = self.files.asset(uri_path);
147 if let Some(base_file_name) = asset_path.file_name() {
148 if let Some(parent) = asset_path.parent() {
149 if parent.is_dir() {
150 let base_file_name = base_file_name.to_string_lossy().into_owned() + &self.render.midfix;
151 for file_path in parent.read_dir()? {
152 let file_path = file_path?.path();
153 if let Some(file_name) = file_path.file_name() {
154 let file_name = file_name.to_string_lossy();
155 if file_name.starts_with(&base_file_name) {
156 let extension = &file_name[base_file_name.len()..];
157 return Ok(Some(String::from(uri_path) + &self.render.midfix + extension));
158 }
159 }
160 }
161 }
162 }
163 }
164
165 Ok(None)
166 }
167}
168
169impl Default for CredenceConfiguration {
170 fn default() -> Self {
171 let mut port = Port::default();
172 port.name = "http".into();
173
174 Self {
175 files: FilesConfiguration::default(),
176 ports: BTreeMap::from([(8000, port)]),
177 requests: RequestsConfiguration::default(),
178 caching: CachingConfiguration::default(),
179 encoding: EncodingConfiguration::default(),
180 render: RenderConfiguration::default(),
181 urls: UrlsConfiguration::default(),
182 definitions: None,
183 }
184 }
185}