diff options
author | gennyble <gen@nyble.dev> | 2024-04-13 05:40:17 -0500 |
---|---|---|
committer | gennyble <gen@nyble.dev> | 2024-04-13 05:40:17 -0500 |
commit | fafb3c3ceaa16e93f69b38e33e64e240573e4875 (patch) | |
tree | c49c9eb94e6c14c089847c02ba156d5566e5b118 /src/main.rs | |
parent | 1b93aecbdc261ca2f7932db2754c6e33487dd9c8 (diff) | |
download | awake-fafb3c3ceaa16e93f69b38e33e64e240573e4875.tar.gz awake-fafb3c3ceaa16e93f69b38e33e64e240573e4875.zip |
:)
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 123 |
1 files changed, 102 insertions, 21 deletions
diff --git a/src/main.rs b/src/main.rs index 29716e8..b43e463 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,11 @@ +mod atomizer; mod error; mod fs; +mod ifc; mod markup; mod settings; mod templated; +mod timeparse; use std::{os::unix::fs::MetadataExt, str::FromStr}; @@ -16,10 +19,12 @@ use axum::{ }; use bempline::{Document, Options}; use camino::Utf8PathBuf; +use confindent::Confindent; pub use error::RuntimeError; use fs::Filesystem; use settings::Settings; use tokio_util::io::ReaderStream; +use tracing_subscriber::{prelude::*, EnvFilter}; use crate::{ fs::{PathResolution, Webpath}, @@ -28,10 +33,35 @@ use crate::{ #[tokio::main] async fn main() { - let fs = Filesystem::new("../inf/served"); + match std::env::args().nth(1).as_deref() { + Some("atomizer") => atomizer::main(), + Some("serve") => + /* fallthrough*/ + { + () + } + _ => (), + } + + tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer()) + .with( + EnvFilter::try_from_default_env() + .or_else(|_| EnvFilter::try_new("info")) + .unwrap(), + ) + .init(); + + let conf = Confindent::from_file(std::env::args().nth(2).unwrap()).unwrap(); + let webroot: Utf8PathBuf = conf.child_parse("Webroot").unwrap(); + let templates = conf.child_value("Templates").unwrap(); + + let fs = Filesystem::new(&webroot); let settings = Settings { - template_dir: Utf8PathBuf::from("../inf/templates"), + template_dir: Utf8PathBuf::from(webroot.join(templates)) + .canonicalize_utf8() + .unwrap(), }; let app = Router::new() @@ -66,30 +96,25 @@ async fn falible_handler( settings: Settings, path: String, ) -> Result<Response, RuntimeError> { - println!("raw = {path}"); + tracing::debug!("webpath = {path}"); let webpath: Webpath = path.parse()?; + let resolve = fs.resolve(&webpath)?; - println!("path = {path}"); - - let PathResolution { - filepath, - is_dirfile, - } = fs.resolve(&webpath)?; - - if !webpath.is_dir() && is_dirfile { - println!("as_dir = {}", webpath.as_dir()); + if !webpath.is_dir() && resolve.is_dirfile { return Ok(redirect(webpath.as_dir())); } - let ext = filepath.extension().unwrap_or_default(); + tracing::info!("serving {webpath}"); + + let ext = resolve.filepath.extension().unwrap_or_default(); if ext != "html" { - send_file(filepath).await + send_file(resolve.filepath).await } else { - let content = Filesystem::read_to_string(&filepath).await?; + let content = Filesystem::read_to_string(&resolve.filepath).await?; match Templated::from_str(&content) { - Ok(templated) => send_template(templated, filepath, settings).await, + Ok(templated) => send_template(templated, resolve, webpath, settings).await, Err(_) => Ok(Response::builder() .header(header::CONTENT_TYPE, "text/html") .body(Body::from(content)) @@ -100,7 +125,7 @@ async fn falible_handler( fn redirect<S: Into<String>>(redirection: S) -> Response { let location = redirection.into(); - println!("redirecting to {location}"); + tracing::info!("redirect to {location}"); Response::builder() .status(StatusCode::TEMPORARY_REDIRECT) .header(header::LOCATION, &location) @@ -113,13 +138,16 @@ const STREAM_AFTER: u64 = 20 * 1024 * 1024; async fn send_file(filepath: Utf8PathBuf) -> Result<Response, RuntimeError> { let ext = filepath.extension().unwrap_or_default(); + let stem = filepath.file_stem().unwrap_or_default(); let mime = match ext { // Text "css" => "text/css", "html" => "text/html", "js" => "text/javascript", - "txt" => "txt/plain", + "txt" => "text/plain", + "xml" if stem.ends_with("atom") => "application/atom+xml", + "xml" => "application/xml", // Multimedia "gif" => "image/gif", @@ -136,6 +164,8 @@ async fn send_file(filepath: Utf8PathBuf) -> Result<Response, RuntimeError> { let metadata = Filesystem::metadata(&filepath)?; if metadata.size() > STREAM_AFTER { + tracing::debug!("large file, streaming to client"); + let file = Filesystem::open(filepath).await?; let stream = ReaderStream::new(file); Ok(response.body(Body::from_stream(stream)).unwrap()) @@ -147,14 +177,18 @@ async fn send_file(filepath: Utf8PathBuf) -> Result<Response, RuntimeError> { async fn send_template( templated: Templated, - path: Utf8PathBuf, + resolve: PathResolution, + webpath: Webpath, settings: Settings, ) -> Result<Response, RuntimeError> { let template_stem = templated.frontmatter.get("template").expect("no template"); let template_name = Utf8PathBuf::from(format!("{template_stem}.html")); let template_path = settings.template_dir.join(template_name); - let filename = path.file_name().expect("template has no filename"); + let filename = resolve + .filepath + .file_name() + .expect("template has no filename"); let mut template = Document::from_file( template_path, @@ -169,6 +203,7 @@ async fn send_template( templated.frontmatter.get("title").unwrap_or(filename), ); + // styles the templated stuff wants let style_pattern = template.get_pattern("styles").unwrap(); for style in templated.frontmatter.get_many("style") { let mut pat = style_pattern.clone(); @@ -176,7 +211,53 @@ async fn send_template( template.set_pattern("styles", pat); } - template.set("main", templated.content); + // path to the file for navigation + let mut path: Vec<&str> = webpath.webcanon.iter().collect(); + // we don't want the directory/filename itself + path.pop(); + + if let Some(path_pattern) = template.get_pattern("path") { + let offset = match templated + .frontmatter + .get("path-offset") + .map(|raw| raw.parse::<usize>()) + { + Some(Ok(offset)) => offset, + None => 0, + Some(Err(_)) => { + tracing::error!( + "path-offset in template {} is not an integer", + resolve.filepath + ); + + 0 + } + }; + + for _ in 0..offset { + path.pop(); + } + + let mut link = Utf8PathBuf::from("/"); + + let mut pat = path_pattern.clone(); + pat.set("path_link", "/"); + pat.set("path_name", "home"); + template.set_pattern("path", pat); + + for part in path { + link.push(part); + + let mut pat = path_pattern.clone(); + pat.set("path_link", &link); + pat.set("path_name", part); + template.set_pattern("path", pat); + } + } + + // insert the page content itself + let markedup = markup::process(&templated.content); + template.set("main", markedup); Ok(Response::builder() .header(header::CONTENT_TYPE, "text/html") |