| 
						
						
							
								
							
						
						
					 | 
					@ -11,6 +11,9 @@ use rocket::{ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    Data, Request, Response, Rocket, | 
					 | 
					 | 
					    Data, Request, Response, Rocket, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					}; | 
					 | 
					 | 
					}; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					use std::thread::sleep; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					use std::time::Duration; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					use crate::CONFIG; | 
					 | 
					 | 
					use crate::CONFIG; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					pub struct AppHeaders(); | 
					 | 
					 | 
					pub struct AppHeaders(); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -99,29 +102,53 @@ impl Fairing for Cors { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					pub struct Cached<R>(R, String); | 
					 | 
					 | 
					pub struct Cached<R> { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    response: R, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    is_immutable: bool, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    ttl: u64, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					impl<R> Cached<R> { | 
					 | 
					 | 
					impl<R> Cached<R> { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    pub fn long(r: R) -> Cached<R> { | 
					 | 
					 | 
					    pub fn long(response: R, is_immutable: bool) -> Cached<R> { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        // 7 days
 | 
					 | 
					 | 
					        Self { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Self::ttl(r, 604800) | 
					 | 
					 | 
					            response, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            is_immutable, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            ttl: 604800, // 7 days
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    pub fn short(r: R) -> Cached<R> { | 
					 | 
					 | 
					    pub fn short(response: R, is_immutable: bool) -> Cached<R> { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        // 10 minutes
 | 
					 | 
					 | 
					        Self { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Self(r, String::from("public, max-age=600")) | 
					 | 
					 | 
					            response, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            is_immutable, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            ttl: 600, // 10 minutes
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					    pub fn ttl(r: R, ttl: u64) -> Cached<R> { | 
					 | 
					 | 
					    pub fn ttl(response: R, ttl: u64, is_immutable: bool) -> Cached<R> { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					        Self(r, format!("public, immutable, max-age={}", ttl)) | 
					 | 
					 | 
					        Self { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            response, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            is_immutable, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            ttl, | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					impl<'r, R: Responder<'r>> Responder<'r> for Cached<R> { | 
					 | 
					 | 
					impl<'r, R: Responder<'r>> Responder<'r> for Cached<R> { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    fn respond_to(self, req: &Request) -> response::Result<'r> { | 
					 | 
					 | 
					    fn respond_to(self, req: &Request) -> response::Result<'r> { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					        match self.0.respond_to(req) { | 
					 | 
					 | 
					        let cache_control_header = if self.is_immutable { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            format!("public, immutable, max-age={}", self.ttl) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        } else { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					            format!("public, max-age={}", self.ttl) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        }; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        let time_now = chrono::Local::now(); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					        match self.response.respond_to(req) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            Ok(mut res) => { | 
					 | 
					 | 
					            Ok(mut res) => { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					                res.set_raw_header("Cache-Control", self.1); | 
					 | 
					 | 
					                res.set_raw_header("Cache-Control", cache_control_header); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                let expiry_time = time_now + chrono::Duration::seconds(self.ttl.try_into().unwrap()); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					                res.set_raw_header("Expires", format_datetime_http(&expiry_time)); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					                Ok(res) | 
					 | 
					 | 
					                Ok(res) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            } | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					            e @ Err(_) => e, | 
					 | 
					 | 
					            e @ Err(_) => e, | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -409,6 +436,17 @@ pub fn format_naive_datetime_local(dt: &NaiveDateTime, fmt: &str) -> String { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    format_datetime_local(&Local.from_utc_datetime(dt), fmt) | 
					 | 
					 | 
					    format_datetime_local(&Local.from_utc_datetime(dt), fmt) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					/// Formats a `DateTime<Local>` as required for HTTP
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					///
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					/// https://httpwg.org/specs/rfc7231.html#http.date
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					pub fn format_datetime_http(dt: &DateTime<Local>) -> String { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    let expiry_time: chrono::DateTime<chrono::Utc> = chrono::DateTime::from_utc(dt.naive_utc(), chrono::Utc); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // HACK: HTTP expects the date to always be GMT (UTC) rather than giving an
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    // offset (which would always be 0 in UTC anyway)
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					    expiry_time.to_rfc2822().replace("+0000", "GMT") | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					//
 | 
					 | 
					 | 
					//
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					// Deployment environment methods
 | 
					 | 
					 | 
					// Deployment environment methods
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					//
 | 
					 | 
					 | 
					//
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -551,8 +589,6 @@ where | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    } | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					use std::{thread::sleep, time::Duration}; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					pub fn retry_db<F, T, E>(func: F, max_tries: u32) -> Result<T, E> | 
					 | 
					 | 
					pub fn retry_db<F, T, E>(func: F, max_tries: u32) -> Result<T, E> | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					where | 
					 | 
					 | 
					where | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					    F: Fn() -> Result<T, E>, | 
					 | 
					 | 
					    F: Fn() -> Result<T, E>, | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					
  |