Mercurial > lbo > hg > analyrics
changeset 37:4347956773fb
Enable caching of fileserver requests
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Sat, 16 Jul 2022 13:20:20 -0700 |
parents | 0c5f8caf6736 |
children | 305224ae5a33 |
files | src/cacheresponder.rs src/main.rs |
diffstat | 2 files changed, 96 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cacheresponder.rs Sat Jul 16 13:20:20 2022 -0700 @@ -0,0 +1,84 @@ +use log::info; + +use std::convert::Into; + +use rocket::data::Data; +use rocket::http::Header; +use rocket::http::Method; +use rocket::request::Request; +use rocket::response::Responder; +use rocket::route::Handler; +use rocket::route::Outcome; +use rocket::route::Route; + +#[derive(Clone, Debug)] +pub struct CacheControl(String); + +impl CacheControl { + pub fn new<S: AsRef<str>>(policy: S) -> CacheControl { + CacheControl(policy.as_ref().to_string()) + } +} + +impl Into<Header<'_>> for CacheControl { + fn into(self) -> Header<'static> { + Header::new("cache-control", self.0) + } +} + +#[derive(Responder)] +pub struct CachedResponder<R> { + inner: R, + cachecontrol: CacheControl, +} + +impl<'r, 'o: 'r, R: Responder<'r, 'o>> CachedResponder<R> { + fn wrap(inner: R, policy: String) -> CachedResponder<R> { + CachedResponder { + inner: inner, + cachecontrol: CacheControl(policy), + } + } +} + +#[derive(Clone)] +pub struct CachedHandler<H: Clone> { + inner: H, + cachecontrol: CacheControl, +} + +unsafe impl<H: Clone + Send> Send for CachedHandler<H> {} +unsafe impl<H: Clone + Sync> Sync for CachedHandler<H> {} + +impl<H: Clone + Handler> CachedHandler<H> { + pub fn wrap(inner: H, policy: CacheControl) -> CachedHandler<H> { + CachedHandler { + inner: inner, + cachecontrol: policy, + } + } +} + +impl<H: Clone + Handler + Into<Vec<Route>>> Into<Vec<Route>> for CachedHandler<H> { + fn into(self) -> Vec<Route> { + // bah + let mut r = self.inner.clone().into(); + assert_eq!(r.len(), 1); + r[0].handler = Box::new(self); + r + } +} + +#[rocket::async_trait] +impl<H: Clone + Handler> Handler for CachedHandler<H> { + async fn handle<'r>(&self, req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r> { + info!("Received request {:?}", req); + match self.inner.handle(req, data).await { + Outcome::Success(mut resp) => { + resp.set_header(Header::new("cache-control", self.cachecontrol.0.clone())); + Outcome::Success(resp) + } + o => o, + } + } +}
--- a/src/main.rs Sat Jul 16 10:45:58 2022 -0700 +++ b/src/main.rs Sat Jul 16 13:20:20 2022 -0700 @@ -1,3 +1,4 @@ +mod cacheresponder; mod configdb; mod db; mod fromparam; @@ -434,12 +435,6 @@ .extract::<CustomConfig>() .expect("custom config"); - let ap = Path::new(cfg.asset_path.as_str()); - let ap = ap - .canonicalize() - .expect("absolute path to asset directory") - .to_path_buf(); - let geoip = match crate::geoip::GeoIP::new(cfg.geodb_path) { Ok(g) => Some(g), Err(e) => { @@ -448,13 +443,23 @@ } }; + let ap = Path::new(cfg.asset_path.as_str()); + let ap = ap + .canonicalize() + .expect("absolute path to asset directory") + .to_path_buf(); + let fileserver = cacheresponder::CachedHandler::wrap( + FileServer::from(ap), + cacheresponder::CacheControl::new("max-age=43200"), + ); + let r = r .attach(ConfigDB::init()) .attach(LogsDB::init()) .attach(Template::fairing()) .attach(rocket::fairing::AdHoc::config::<CustomConfig>()) .manage(geoip) - .mount("/static", FileServer::from(ap)) + .mount("/static", fileserver) .mount( "/", rocket::routes![