diff --git a/.env.example b/.env.example index 9331dcb..14e8b69 100644 --- a/.env.example +++ b/.env.example @@ -5,4 +5,4 @@ KEEP_GEMINI_EXACT=gemini://fuwn.me/skills # KEEP_GEMINI_DOMAIN=fuwn.me # PROXY_BY_DEFAULT=true FAVICON_EXTERNAL=https://host.fuwn.me/8te8lw0lxm03.webp -PLAIN_TEXT_ROUTE=/robots.txt +PLAIN_TEXT_ROUTE=/robots.txt,*.xml diff --git a/Configuration.md b/Configuration.md index 4815e13..f58d2c7 100644 --- a/Configuration.md +++ b/Configuration.md @@ -88,8 +88,11 @@ FAVICON_EXTERNAL=https://example.com/favicon.ico A comma-separated list of paths to treat as plain text routes +These patterns do not support regular expressions, but do support the use of `*` +as a wildcard. + ```dotenv -PLAIN_TEXT_ROUTE=/robots.txt,/license.txt +PLAIN_TEXT_ROUTE=/robots.txt,/license.txt,*.xml ``` ## `MATHJAX` diff --git a/src/response.rs b/src/response.rs index 91764b9..3521e99 100644 --- a/src/response.rs +++ b/src/response.rs @@ -291,7 +291,10 @@ For example: to proxy "gemini://fuwn.me/uptime", visit "/proxy/fuwn.me/uptime".< )); if let Ok(plain_texts) = var("PLAIN_TEXT_ROUTE") { - if plain_texts.split(',').any(|r| r == req.path()) { + if plain_texts.split(',').any(|r| { + path_matches_pattern(r, req.path()) + || path_matches_pattern(r, req.path().trim_end_matches('/')) + }) { return Ok( HttpResponse::Ok().body(response.content().clone().unwrap_or_default()), ); @@ -304,3 +307,36 @@ For example: to proxy "gemini://fuwn.me/uptime", visit "/proxy/fuwn.me/uptime".< .body(html_context), ) } + +fn path_matches_pattern(pattern: &str, path: &str) -> bool { + let parts: Vec<&str> = pattern.split('*').collect(); + let mut position = 0; + + if !pattern.starts_with('*') { + if let Some(part) = parts.first() { + if !path.starts_with(part) { + return false; + } + + position = part.len(); + } + } + + for part in &parts[1..parts.len() - 1] { + if let Some(found_position) = path[position..].find(part) { + position += found_position + part.len(); + } else { + return false; + } + } + + if !pattern.ends_with('*') { + if let Some(part) = parts.last() { + if !path[position..].ends_with(part) { + return false; + } + } + } + + true +}