* add basic caching support

* Use hash of static dir instead of rand

* Add support for ETag
This commit is contained in:
fdb-hiroshima
2019-03-16 15:33:28 +01:00
committed by GitHub
parent 90baf9beb1
commit a2b2e37aa0
6 changed files with 104 additions and 17 deletions
+1
View File
@@ -189,6 +189,7 @@ Then try to restart Plume.
routes::session::password_reset_form,
routes::session::password_reset,
routes::plume_static_files,
routes::static_files,
routes::tags::tag,
+24 -4
View File
@@ -1,6 +1,9 @@
use atom_syndication::{ContentBuilder, Entry, EntryBuilder, LinkBuilder, Person, PersonBuilder};
use rocket::{
http::{RawStr, Status, uri::{FromUriParam, Query}},
http::{
RawStr, Status, uri::{FromUriParam, Query},
hyper::header::{CacheControl, CacheDirective}
},
Outcome,
request::{self, FromFormValue, FromRequest, Request},
response::NamedFile,
@@ -101,7 +104,24 @@ pub mod user;
pub mod search;
pub mod well_known;
#[get("/static/<file..>", rank = 2)]
pub fn static_files(file: PathBuf) -> Option<NamedFile> {
NamedFile::open(Path::new("static/").join(file)).ok()
#[derive(Responder)]
#[response()]
pub struct CachedFile {
inner: NamedFile,
cache_control: CacheControl
}
#[get("/static/cached/<_build_id>/<file..>", rank = 2)]
pub fn plume_static_files(file: PathBuf, _build_id: &RawStr) -> Option<CachedFile> {
static_files(file)
}
#[get("/static/<file..>", rank = 3)]
pub fn static_files(file: PathBuf) -> Option<CachedFile> {
NamedFile::open(Path::new("static/").join(file)).ok()
.map(|f|
CachedFile {
inner: f,
cache_control: CacheControl(vec![CacheDirective::MaxAge(60*60*24*30)])
})
}
+35 -4
View File
@@ -1,19 +1,50 @@
use plume_models::{Connection, notifications::*, users::User};
use rocket::response::Content;
use rocket::http::{Method, Status};
use rocket::http::hyper::header::{ETag, EntityTag};
use rocket::request::Request;
use rocket::response::{self, Response, Responder, content::Html as HtmlCt};
use rocket_i18n::Catalog;
use std::collections::hash_map::DefaultHasher;
use std::hash::Hasher;
use templates::Html;
pub use askama_escape::escape;
pub static CACHE_NAME: &str = env!("CACHE_ID");
pub type BaseContext<'a> = &'a(&'a Connection, &'a Catalog, Option<User>);
pub type Ructe = Content<Vec<u8>>;
#[derive(Debug)]
pub struct Ructe(pub Vec<u8>);
impl<'r> Responder<'r> for Ructe {
fn respond_to(self, r: &Request) -> response::Result<'r> {
//if method is not Get or page contain a form, no caching
if r.method() != Method::Get || self.0.windows(6).any(|w| w == b"<form ") {
return HtmlCt(self.0).respond_to(r);
}
let mut hasher = DefaultHasher::new();
hasher.write(&self.0);
let etag = format!("{:x}", hasher.finish());
if r.headers().get("If-None-Match").any(|s| &s[1..s.len()-1] == etag) {
Response::build()
.status(Status::NotModified)
.header(ETag(EntityTag::strong(etag)))
.ok()
} else {
Response::build()
.merge(HtmlCt(self.0).respond_to(r)?)
.header(ETag(EntityTag::strong(etag)))
.ok()
}
}
}
#[macro_export]
macro_rules! render {
($group:tt :: $page:tt ( $( $param:expr ),* ) ) => {
{
use rocket::{http::ContentType, response::Content};
use templates;
let mut res = vec![];
@@ -23,7 +54,7 @@ macro_rules! render {
$param
),*
).unwrap();
Content(ContentType::HTML, res)
Ructe(res)
}
}
}