Skip to content

Commit

Permalink
Adds error page template (and 404 fallback)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jerboa-app committed Oct 23, 2024
1 parent 2d2c5fe commit 81e88f7
Show file tree
Hide file tree
Showing 10 changed files with 258 additions and 73 deletions.
58 changes: 58 additions & 0 deletions error_template.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Error ERROR_CODE</title>
</head>

<style>
.page {
display: table;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}

.content {
display: table-cell;
vertical-align: middle;
margin-left: auto;
margin-right: auto;
width: 75vw;
text-align: center;
}

a:link, a:visited {
transition-duration: 0.4s;
border: none;
color: rgb(25, 25, 25);
border: 2px solid rgb(25, 25, 25);
padding: 16px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
transition-duration: 0.4s;
cursor: pointer;
}

a:hover, a:active {
background-color: rgb(25, 25, 25);
color: rgb(230, 230, 230);
}
</style>

<body>
<div class="page">
<div class="content">
<h1>That's a ERROR_CODE error.</h1>
<a href="LINK_TO_HOME">Let's go home.</a>
</div>
</div>
</body>
</html>
17 changes: 10 additions & 7 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ impl ThrottleConfig
/// - ```server_cache_period_seconds: u16```: internal cache period if content is not static
/// - ```static_content: Option<bool>```: all content is immutably cached at launch
/// - ```ignore_regexes: Option<Vec<String>>```: do not serve content matching any of these patterns
/// - ```generate_sitemap: Option<bool>```: sitemap.xml will be automatically generated (and updated)
/// - ```generate_sitemap: Option<bool>```: sitemap.xml will be automatically generated (and updated)
/// - ```message_on_sitemap_reload: Option<bool>```: optionally send Discord notifications when sitemap is reloaded
/// - ```error_template: Option<String>```: path to error template page.
#[derive(Clone, Serialize, Deserialize)]
pub struct ContentConfig
{
Expand All @@ -90,7 +91,8 @@ pub struct ContentConfig
pub server_cache_period_seconds: u16,
pub static_content: Option<bool>,
pub generate_sitemap: Option<bool>,
pub message_on_sitemap_reload: Option<bool>
pub message_on_sitemap_reload: Option<bool>,
pub error_template: Option<String>
}

impl ContentConfig
Expand All @@ -107,7 +109,8 @@ impl ContentConfig
server_cache_period_seconds: 3600,
static_content: Some(false),
generate_sitemap: Some(true),
message_on_sitemap_reload: Some(false)
message_on_sitemap_reload: Some(false),
error_template: None
}
}
}
Expand All @@ -116,7 +119,7 @@ impl ContentConfig
/// - ```key_path```: optional location of ssh key (ssh connection will be used)
/// - ```user```: user name for authentication
/// - ```passphrase```: passphrase for ssh key or for user-pass auth
/// <div class="warning"><p>If using ssh keys be sure the host is added to ~/ssh/known_hosts for
/// <div class="warning"><p>If using ssh keys be sure the host is added to ~/ssh/known_hosts for
///the user that runs busser, including root</p>
#[derive(Clone, Serialize, Deserialize)]
pub struct GitAuthConfig
Expand Down Expand Up @@ -188,7 +191,7 @@ pub struct Config
pub relay: Option<Vec<RelayConfig>>
}

impl Config
impl Config
{
pub fn default() -> Config
{
Expand Down Expand Up @@ -239,7 +242,7 @@ pub fn read_config(path: &str) -> Option<Config>
let config: Config = match serde_json::from_str(&data)
{
Ok(data) => {data},
Err(why) =>
Err(why) =>
{
crate::debug(format!("Error reading configuration file {}\n{}", path, why), None);
return None
Expand All @@ -248,7 +251,7 @@ pub fn read_config(path: &str) -> Option<Config>

Some(config)
}
else
else
{
crate::debug(format!("Error configuration file {} does not exist", path), None);
None
Expand Down
91 changes: 91 additions & 0 deletions src/content/error_page.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use crate::{config::Config, filesystem::file::read_file_utf8};

pub const DEFAULT_BODY: &str = r#"<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Error ERROR_CODE</title>
</head>
<style>
.page {
display: table;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
.content {
display: table-cell;
vertical-align: middle;
margin-left: auto;
margin-right: auto;
width: 75vw;
text-align: center;
}
a:link, a:visited {
transition-duration: 0.4s;
border: none;
color: rgb(25, 25, 25);
border: 2px solid rgb(25, 25, 25);
padding: 16px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
transition-duration: 0.4s;
cursor: pointer;
}
a:hover, a:active {
background-color: rgb(25, 25, 25);
color: rgb(230, 230, 230);
}
</style>
<body>
<div class="page">
<div class="content">
<h1>That's a ERROR_CODE error.</h1>
<a href="LINK_TO_HOME">Let's go home.</a>
</div>
</div>
</body>
</html>
"#;

pub struct ErrorPage
{
pub body_template: String
}

impl ErrorPage
{
fn expand_template(template: String, config: &Config) -> String
{
template.replace("LINK_TO_HOME", &format!("https://{}",&config.domain))
}

pub fn expand_error_code(&self, code: &str) -> String
{
self.body_template.replace("ERROR_CODE", code)
}

pub fn from(config: &Config) -> ErrorPage
{
if let Some(ref path) = config.content.error_template
{
if let Some(body) = read_file_utf8(&path)
{
return ErrorPage {body_template: Self::expand_template(body, config)}
}
}
ErrorPage {body_template: Self::expand_template(DEFAULT_BODY.to_string(), config)}
}
}
39 changes: 20 additions & 19 deletions src/content/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ use self::mime_type::{Mime, MIME};
pub mod mime_type;
pub mod filter;
pub mod sitemap;
pub mod error_page;

/// Store web content
///
/// Store web content
///
/// - The body is unpopulated until [Content::load_from_file] is called
/// - The body may be converted to a utf8 string using [Content::utf8_body]
/// - A hash of the file is used to check it is stale, used by [Observed]
Expand All @@ -38,9 +39,9 @@ pub struct Content
tag_insertion: bool
}

pub trait HasUir
pub trait HasUir
{
fn get_uri(&self) -> String;
fn get_uri(&self) -> String;
}

impl PartialEq for Content
Expand Down Expand Up @@ -96,7 +97,7 @@ impl Observed for Content
}
}

fn last_refreshed(&self) -> SystemTime
fn last_refreshed(&self) -> SystemTime
{
self.last_refreshed.clone()
}
Expand All @@ -114,11 +115,11 @@ impl Content
{
pub fn new(uri: &str, disk_path: &str, server_cache: u16, browser_cache: u16, tag_insertion: bool) -> Content
{
Content
{
uri: uri.to_string(),
body: vec![],
disk_path: disk_path.to_string(),
Content
{
uri: uri.to_string(),
body: vec![],
disk_path: disk_path.to_string(),
content_type: <MIME as Mime>::infer_mime_type(disk_path),
server_cache_period_seconds: server_cache,
browser_cache_period_seconds: browser_cache,
Expand All @@ -145,14 +146,14 @@ impl Content
{
match self.read_bytes()
{
Some(data) =>
Some(data) =>
{
self.body = data.clone();
self.hash = hash(data);
self.last_refreshed = SystemTime::now();
Ok(())
}
None =>
None =>
{
self.last_refreshed = SystemTime::now();
Err(FileError { why: format!("Could not read bytes from {}", self.disk_path)})
Expand Down Expand Up @@ -180,7 +181,7 @@ impl Content
let preview_body = match self.utf8_body()
{
Ok(s) => s[0..min(s.len(), n)].to_string(),
Err(_e) =>
Err(_e) =>
{
dump_bytes(&self.body)[0..min(self.body.len(), n)].to_string()
}
Expand All @@ -193,13 +194,13 @@ impl Content
/// this may be disabled by launching as busser --no-tagging
pub fn insert_tag(body: String)
-> String
{
{
format!("<!--Hosted by Busser {}, https://github.com/JerboaBurrow/Busser-->\n{}", program_version(), body)
}

impl IntoResponse for Content {
fn into_response(self) -> Response {

let mut response = if self.content_type == MIME::TextHtml
{
let mut string_body = match self.utf8_body()
Expand Down Expand Up @@ -229,22 +230,22 @@ impl IntoResponse for Content {

response.headers_mut()
.insert("cache-control", format!("public, max-age={}", self.browser_cache_period_seconds).parse().unwrap());

response
}
}

pub fn is_page(uri: &str, domain: &str) -> bool
{
if uri == "/"
if uri == "/"
{
return true
}

let domain_escaped = domain.replace("https://", "").replace("http://", "").replace(".", r"\.");
match Regex::new(format!(r"((^|(http)(s|)://){})(/|/[^\.]+|/[^\.]+.html|$)$",domain_escaped).as_str())
{
Ok(re) =>
Ok(re) =>
{
re.is_match(uri)
},
Expand Down
Loading

0 comments on commit 81e88f7

Please sign in to comment.