use std::path::{Component, Path, PathBuf};
use camel_api::CamelError;
use crate::config::ExternalTemplateLimitsConfig;
#[derive(Debug, Clone, PartialEq, Eq)]
#[allow(dead_code)] pub(crate) struct TemplateEndpointConfig {
pub(crate) entry_abs_path: PathBuf,
pub(crate) limits: ExternalTemplateLimitsConfig,
}
#[allow(dead_code)] pub(crate) fn parse_template_uri(
uri: &str,
limits: ExternalTemplateLimitsConfig,
) -> Result<TemplateEndpointConfig, CamelError> {
let (outer_scheme, rest) = uri.split_once(':').ok_or_else(|| {
CamelError::Config(
"template URI must be file:///<abs-path>: missing scheme separator".into(),
)
})?;
if outer_scheme != "template" {
return Err(CamelError::Config(format!(
"template URI must be file:///<abs-path>: unknown outer scheme '{outer_scheme}'",
)));
}
let (inner_scheme, path_start) = rest.split_once(':').ok_or_else(|| {
CamelError::Config("template URI must be file:///<abs-path>: missing inner scheme".into())
})?;
if inner_scheme != "file" {
return Err(CamelError::Config(format!(
"template URI must be file:///<abs-path>: unknown inner scheme '{inner_scheme}'",
)));
}
let path_str = path_start.strip_prefix("//").ok_or_else(|| {
CamelError::Config(
"template URI must be file:///<abs-path>: expected file:///<abs-path>".into(),
)
})?;
if path_str.is_empty() {
return Err(CamelError::Config(
"template URI must be file:///<abs-path>: path is empty".into(),
));
}
let path = Path::new(path_str);
if !path.is_absolute() {
return Err(CamelError::Config(format!(
"template URI must be file:///<abs-path>: path '{path_str}' is not absolute",
)));
}
if path.components().any(|c| matches!(c, Component::ParentDir)) {
return Err(CamelError::Config(format!(
"template URI must be file:///<abs-path>: path '{path_str}' contains '..' segments",
)));
}
Ok(TemplateEndpointConfig {
entry_abs_path: path.to_path_buf(),
limits,
})
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn parse_valid_file_uri() {
let uri = "template:file:///srv/t/page.html";
let limits = ExternalTemplateLimitsConfig::default();
let result = parse_template_uri(uri, limits);
let config = result.expect("valid file URI should parse");
assert_eq!(config.entry_abs_path, PathBuf::from("/srv/t/page.html"));
}
#[test]
fn parse_rejects_bare_path() {
let uri = "template:/srv/t/page.html";
let limits = ExternalTemplateLimitsConfig::default();
let result = parse_template_uri(uri, limits);
assert!(result.is_err());
assert!(matches!(result, Err(CamelError::Config(_))));
}
#[test]
fn parse_rejects_non_file_scheme() {
let uri = "template:http://h/p";
let limits = ExternalTemplateLimitsConfig::default();
let result = parse_template_uri(uri, limits);
assert!(result.is_err());
assert!(matches!(result, Err(CamelError::Config(_))));
}
}