[−][src]Struct ructe::StaticFiles
Handler for static files.
Apart from handling templates for dynamic content, ructe also helps with constants for static content.
Most sites that need HTML templates also needs some static resources. Maybe one or several CSS files, some javascript, and / or pictures. A good way to reduce network round-trips is to use a far expires header to tell the browser it can cache those files and don't need to check if they have changed. But what if the files do change? Then pretty much the only way to make sure the browser gets the updated file is to change the URL to the file as well.
Ructe can create content-dependent file names for static files.
If you have an image.png
, ructe may call it image-SomeHash.png
where SomeHash
is 8 url-safe base64 characters encoding 48 bits
of a md5 sum of the file.
Each static file will be available as a
StaticFile
struct instance in
your templates::statics
module.
Also, the const STATICS
array in the same module will contain a
reference to each of those instances.
Actually serving the file is a job for a web framework like iron, nickel or rocket, but ructe helps by packing the file contents into a constant struct that you can access from rust code.
Overview
This section describes how to set up your project to serve static content using ructe.
To do this, the first step is to add a line in build.rs
telling
ructe to find and transpile your static files:
let mut ructe = Ructe::from_env()?; ructe.statics()?.add_files("static")?;
Then you need to link to the encoded file.
For an image, you probably want to link it from an <img>
tag in
a template. That can be done like this:
@use super::statics::image_png;
@()
<img alt="Something" src="/static/@image_png.name">
So, what has happened here?
First, assuming the static
directory in your
$CARGO_MANIFEST_DIR
contained a file name image.png
, your
templates::statics
module (which is reachable as super::statics
from inside a template) will contain a
pub static image_png: StaticFile
which can be imported and used
in both templates and rust code.
A StaticFile
has a field named name
which is a &'static str
containing the name with the generated hash, image-SomeHash.png
.
The next step is that a browser actually sends a request for
/static/image-SomeHash.png
and your server needs to deliver it.
Here, things depend on your web framework, so we start with some
pseudo code.
Full examples for warp, gotham, nickel, and iron is
available in the ructe repository.
/// A hypothetical web framework calls this each /static/... request, /// with the name component of the URL as the name argument. fn serve_static(name: &str) -> Response { if let Some(data) = StaticFile::get(name) { Response::Ok(data.content) } else { Response::NotFound } }
The StaticFile::get
function returns the &'static StaticFile
for a given file name if the file exists.
This is a reference to the same struct that we used by the name
image_png
in the template.
Besides the name
field (which will be equal to the argument, or
get
would not have returned this StaticFile
), there is a
content: &'static [u8]
field which contains the actual file
data.
Content-types
How to get the content type of static files.
Ructe has support for making the content-type of each static
file availiable using the
mime crate.
Since mime version 0.3.0 was a breaking change of how the
mime::Mime
type was implemented, and both Nickel and Iron
currently require the old version (0.2.x), ructe provides
support for both mime 0.2.x and mime 0.3.x with separate
feature flags.
Mime 0.2.x
To use the mime 0.2.x support, enable the mime02
feature and
add mime 0.2.x as a dependency:
[build-dependencies]
ructe = { version = "^0.3.2", features = ["mime02"] }
[dependencies]
mime = "~0.2"
A Mime
as implemented in mime
version 0.2.x cannot be
created statically, so instead a StaticFile
provides
pub fn mime(&self) -> Mime
.
use templates::statics::image_png; assert_eq!(format!("Type is {}", image_png.mime()), "Type is image/png");
Mime 0.3.x
To use the mime 0.3.x support, enable the mime3
feature and
add mime 0.3.x as a dependency:
[build-dependencies]
ructe = { version = "^0.3.2", features = ["mime03"] }
[dependencies]
mime = "~0.3"
From version 0.3, the mime
crates supports creating const
static Mime
objects, so with this feature, a StaticFile
simply has a pub mime: &'static Mime
field.
use templates::statics::image_png; assert_eq!(format!("Type is {}", image_png.mime), "Type is image/png");
Methods
impl StaticFiles
[src]
pub fn new(outdir: &Path) -> Result<Self>
[src]
Use the statics() method of struct Ructe instead
Create a new set of static files.
There should only be one StaticFiles
for a set of compiled templates.
The outdir
should be the same as in the call to compile_templates
.
From version 0.6 of ructe,
the statics()
method of struct Ructe
should be used instead of this method.
pub fn add_files(&mut self, indir: impl AsRef<Path>) -> Result<()>
[src]
Add all files from a specific directory, indir
, as static files.
pub fn add_files_as(&mut self, indir: impl AsRef<Path>, to: &str) -> Result<()>
[src]
Add all files from a specific directory, indir
, as static files.
The to
string is used as a directory path of the resulting
urls, the file names are taken as is, without adding any hash.
This is usefull for resources used by preexisting javascript
packages, where it might be hard to change the used urls.
pub fn add_file(&mut self, path: impl AsRef<Path>) -> Result<()>
[src]
Add one specific file as a static file.
Create a name to use in the url like name-hash.ext
where
name and ext are the name and extension from path
and has is
a few url-friendly bytes from a hash of the file content.
pub fn add_file_as(
&mut self,
path: impl AsRef<Path>,
url_name: &str
) -> Result<()>
[src]
&mut self,
path: impl AsRef<Path>,
url_name: &str
) -> Result<()>
Add one specific file as a static file.
Use url_name
in the url without adding any hash characters.
pub fn add_file_data<P>(&mut self, path: P, data: &[u8]) -> Result<()> where
P: AsRef<Path>,
[src]
P: AsRef<Path>,
Add a resource by its name and content, without reading an actual file.
The path
parameter is used only to create a file name, the actual
content of the static file will be the data
parameter.
A hash will be added to the file name, just as for
file-sourced statics.
Examples
With the folloing code in build.rs
:
let mut statics = ructe.statics()?; statics.add_file_data("black.css", b"body{color:black}\n");
A StaticFile
named black_css
will be defined in the
templates::statics
module of your crate:
assert_eq!(statics::black_css.name, "black-r3rltVhW.css");
pub fn get_names(&self) -> &BTreeMap<String, String>
[src]
Get a mapping of names, from without hash to with.
let mut statics = ructe.statics()?; statics.add_file_data("black.css", b"body{color:black}\n"); statics.add_file_data("blue.css", b"body{color:blue}\n"); assert_eq!( statics.get_names().iter() .map(|(a, b)| format!("{} -> {}", a, b)) .collect::<Vec<_>>(), vec!["black_css -> black-r3rltVhW.css".to_string(), "blue_css -> blue-GZGxfXag.css".to_string()], );
Trait Implementations
impl Drop for StaticFiles
[src]
Auto Trait Implementations
impl Send for StaticFiles
impl Sync for StaticFiles
Blanket Implementations
impl<T, U> Into<U> for T where
U: From<T>,
[src]
U: From<T>,
impl<T> From<T> for T
[src]
impl<T, U> TryFrom<U> for T where
U: Into<T>,
[src]
U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
[src]
impl<T, U> TryInto<U> for T where
U: TryFrom<T>,
[src]
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
The type returned in the event of a conversion error.
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
[src]
impl<T> BorrowMut<T> for T where
T: ?Sized,
[src]
T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
[src]
impl<T> Borrow<T> for T where
T: ?Sized,
[src]
T: ?Sized,
impl<T> Any for T where
T: 'static + ?Sized,
[src]
T: 'static + ?Sized,