use crate::fs::config::get_root_dir;
use anyhow::{anyhow, Result};
use std::path::{Path, PathBuf};
use url::Url;
pub fn url_to_path(url_str: &str) -> Result<PathBuf> {
let url = Url::parse(url_str)?;
let host = url.host_str().ok_or_else(|| anyhow!("URL missing host"))?;
let port = url.port();
let mut domain_dir = host.to_string();
if let Some(p) = port {
domain_dir.push_str(&format!("+{}", p));
}
let root = get_root_dir()?;
let mut path = root.join(domain_dir);
for segment in url.path_segments().unwrap_or_else(|| "".split('/')) {
path.push(segment);
}
if url.path().ends_with('/') {
path.push("index");
}
Ok(path)
}
pub fn path_to_url(path: &Path) -> Result<String> {
let root = get_root_dir()?;
let relative = path
.strip_prefix(&root)
.map_err(|_| anyhow!("Path is not within BraidFS root"))?;
let mut components = relative.components();
let domain_comp = components.next().ok_or_else(|| anyhow!("Path too short"))?;
let domain_str = domain_comp.as_os_str().to_string_lossy();
if domain_str.starts_with('.') {
return Err(anyhow!("Ignoring dotfile/directory"));
}
let (host, port) = if let Some((h, p)) = domain_str.rsplit_once('+') {
(h, Some(p.parse::<u16>()?))
} else {
(domain_str.as_ref(), None)
};
let scheme = if host == "localhost" || host == "127.0.0.1" {
"http"
} else {
"https"
};
let mut url = Url::parse(&format!("{}://{}", scheme, host))?;
if let Some(p) = port {
url.set_port(Some(p)).map_err(|_| anyhow!("Invalid port"))?;
}
let mut path_segments = Vec::new();
for comp in components {
path_segments.push(comp.as_os_str().to_string_lossy().to_string());
}
if let Some(last) = path_segments.last() {
if last == "index" {
path_segments.pop();
}
}
url.path_segments_mut()
.map_err(|_| anyhow!("Cannot be base"))?
.extend(path_segments);
Ok(url.to_string())
}
pub fn path_join(parent: &str, name: &str) -> String {
if parent == "/" {
format!("/{}", name)
} else {
format!("{}/{}", parent, name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_url_to_path() {
}
#[test]
fn test_path_join() {
assert_eq!(path_join("/", "foo"), "/foo");
assert_eq!(path_join("/bar", "baz"), "/bar/baz");
}
}