agate

Simple gemini server for static files
git clone https://github.com/mbrubeck/agate.git
Log | Files | Refs | README

commit bd9ed3255a8c43d51a6d71edc912d17319f43443
parent 8fd9ca15c3df8757b0268f9be49a952142fb333f
Author: Johann150 <johann.galle@protonmail.com>
Date:   Thu, 11 Feb 2021 08:57:59 +0100

add central configuration mode

also slight correction of the documentation because we are now using YAML
(a space is now required behind the colon)

Diffstat:
MCHANGELOG.md | 2++
MREADME.md | 10++++++----
Msrc/main.rs | 29++++++++++++++++++++++-------
Msrc/metadata.rs | 7++++++-
4 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md @@ -13,8 +13,10 @@ Thank you to @gegeweb for contributing to this release. * You can now supply multiple `--hostname`s to enable basic vhosts (#28). * Disabling support for TLSv1.2 can now be done using the `--only-tls13` flag, but this is *NOT RECOMMENDED* (#12). * The tools now also contain a startup script for FreeBSD (#13). +* Using central config mode (flag `-C`), all configuration can be done in one `.meta` file (see README.md for details). ### Changed +* The configuration files are now parsed as YAML. The syntax only changes in that a space is now required behind the colon. * The changelog is now also kept in this file in addition to the GitHub releases. * Certificate chain and key file are now only loaded once at startup, certificate changes need a restart to take effect. diff --git a/README.md b/README.md @@ -67,7 +67,7 @@ A file called `index.gmi` will always take precedence over a directory listing. You can put a file called `.meta` in a directory. This file stores some metadata about these files which Agate will use when serving these files. The file should be UTF-8 encoded. Like the `.directory-listing-ok` file, this file does not have an effect on sub-directories. (*1) This file is parsed as a YAML file and should contain a "hash" datatype with file names as the keys. This means: -Lines starting with a `#` are comments and will be ignored like empty lines. All other lines must start with a file name, followed by a colon and then the metadata. +Lines starting with a `#` are comments and will be ignored like empty lines. All other lines must start with a file name, followed by a colon and a space and then the metadata. The metadata can take one of four possible forms: 1. empty @@ -85,11 +85,13 @@ If a line violates the format or looks like case 3, but is incorrect, it might b Such a configuration file might look like this: ```text # This line will be ignored. -index.gmi:;lang=en-UK -LICENSE:text/plain;charset=UTF-8 -gone.gmi:52 This file is no longer here, sorry. +index.gmi: ;lang=en-UK +LICENSE: text/plain;charset=UTF-8 +gone.gmi: 52 This file is no longer here, sorry. ``` +You can enable a central configuration file with the `-C` flag (or the long version `--central-conf`). In this case Agate will always look for the `.meta` configuration file in the content root directory and will ignore `.meta` files in other directories. + (*1) It is *theoretically* possible to specify information on files which are in sub-directories. The problem would only be to make sure that this file is loaded before the respective path/file is requested. This is because Agate does not actively check that the "no sub-directories" regulation is met. In fact this might be dropped in a change of configuration format in the foreseeable future. ### Logging Verbosity diff --git a/src/main.rs b/src/main.rs @@ -9,8 +9,15 @@ use { Certificate, NoClientAuth, PrivateKey, ServerConfig, }, std::{ - borrow::Cow, error::Error, ffi::OsStr, fmt::Write, fs::File, io::BufReader, - net::SocketAddr, path::Path, sync::Arc, + borrow::Cow, + error::Error, + ffi::OsStr, + fmt::Write, + fs::File, + io::BufReader, + net::SocketAddr, + path::{Path, PathBuf}, + sync::Arc, }, tokio::{ io::{AsyncReadExt, AsyncWriteExt}, @@ -67,7 +74,7 @@ static ARGS: Lazy<Args> = Lazy::new(|| { struct Args { addrs: Vec<SocketAddr>, - content_dir: String, + content_dir: PathBuf, cert_chain: Vec<Certificate>, key: PrivateKey, hostnames: Vec<Host>, @@ -76,6 +83,7 @@ struct Args { serve_secret: bool, log_ips: bool, only_tls13: bool, + central_config: bool, } fn args() -> Result<Args> { @@ -130,6 +138,11 @@ fn args() -> Result<Args> { "Enable serving secret files (files/directories starting with a dot)", ); opts.optflag("", "log-ip", "Output IP addresses when logging"); + opts.optflag( + "C", + "central-conf", + "Use a central .meta file in the content root directory.", + ); let matches = opts.parse(&args[1..]).map_err(|f| f.to_string())?; if matches.opt_present("h") { @@ -176,14 +189,16 @@ fn args() -> Result<Args> { serve_secret: matches.opt_present("serve-secret"), log_ips: matches.opt_present("log-ip"), only_tls13: matches.opt_present("only-tls13"), + central_config: matches.opt_present("central-conf"), }) } -fn check_path(s: String) -> Result<String, String> { - if Path::new(&s).exists() { - Ok(s) +fn check_path(s: String) -> Result<PathBuf, String> { + let p = PathBuf::from(s); + if p.as_path().exists() { + Ok(p) } else { - Err(format!("No such file: {}", s)) + Err(format!("No such file: {:?}", p)) } } diff --git a/src/metadata.rs b/src/metadata.rs @@ -193,7 +193,12 @@ impl FileOptions { /// working/content directory. If inconsisten file paths are used, this can /// lead to loading and storing sidecar files multiple times. pub fn get(&mut self, file: &PathBuf) -> PresetMeta { - let dir = file.parent().expect("no parent directory").to_path_buf(); + let dir = if super::ARGS.central_config { + super::ARGS.content_dir.clone() + } else { + file.parent().expect("no parent directory").to_path_buf() + }; + if self.check_outdated(&dir) { self.read_database(&dir); }