From 3a541aed237ab74c6a1a81cc3728e035722ad082 Mon Sep 17 00:00:00 2001 From: Gunwant Jain Date: Tue, 18 Jan 2022 21:33:03 +0530 Subject: [PATCH] Templates: embed the templates in-binary Rocket's templating is not exactly friendly when it comes to embedding in-binary. Rocket's template fairing requires a `template_dir` directory pointing to the directory containing templates. A quick workaround to this would be to have custom fairings with `template_dir` merged with the value `.` But in bare-metal scenarios like what docker's scratch image mimics, we don't exactly have a '.' file, so instead for this very project, I have to point the `template_dir` to the `upload` folder, which is created by `bin` on execution. Checkout the Dockerfile for more info Signed-off-by: Gunwant Jain --- Dockerfile | 14 ++++---------- docker-compose.yml | 8 ++++---- src/main.rs | 44 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/Dockerfile b/Dockerfile index cce2ef8..89ede34 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,8 +2,6 @@ FROM rust as builder WORKDIR /app COPY . . -# scratch does not have the mkdir binary, so we create a folder here -RUN mkdir -p empty_upload ARG ARCH RUN __ARCH="$(dpkg --print-architecture)"; \ @@ -24,15 +22,11 @@ RUN cargo clean ###### Runner Image FROM scratch as runner -COPY --from=builder /app/empty_upload upload -COPY ./contrib/cli/client upload/client -COPY ./templates templates -COPY ./static static -COPY ./themes themes COPY --from=builder /usr/local/cargo/bin/bin . -ENV ROCKET_ADDRESS=0.0.0.0 -ENV ROCKET_PORT=6162 - +ENV BIN_ADDRESS=0.0.0.0 +# Some hax required since we are running on scratch +ENV BIN_TEMPLATE_DIR=upload EXPOSE 6162 + CMD ["./bin"] diff --git a/docker-compose.yml b/docker-compose.yml index 07ffdc2..e77c4bb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,9 +4,9 @@ services: image: wantguns/bin container_name: pastebin ports: - - 127.0.0.1:6162:6162 + - 127.0.0.1:6163:6163 environment: - - ROCKET_PORT=6162 - - ROCKET_LIMITS={form="16 MiB"} + - BIN_PORT=6163 + - BIN_LIMITS={form="16 MiB"} volumes: - - ./upload:/app/upload # upload folder will have your pastes + - ./upload:/upload # upload folder will have your pastes diff --git a/src/main.rs b/src/main.rs index 34676cb..35085fc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,12 +3,35 @@ extern crate rocket; use std::{fs, net::IpAddr, path::PathBuf}; use clap::Parser; -use rocket::shield::{NoSniff, Shield}; -use rocket_dyn_templates::Template; +use rocket::{shield::{NoSniff, Shield}, figment::{providers::Env, Figment}}; +use rocket_dyn_templates::{tera::Tera, Template}; +use rust_embed::RustEmbed; mod models; mod routes; +#[derive(RustEmbed)] +#[folder = "templates/"] +struct EmbeddedTemplates; + +fn setup_tera_engine(tera: &mut Tera) { + // Register templates + let base_html = EmbeddedTemplates::get("base.html.tera").unwrap(); + let index_html = EmbeddedTemplates::get("index.html.tera").unwrap(); + let pretty_html = EmbeddedTemplates::get("pretty.html.tera").unwrap(); + + // and shove them in the tera instance + tera.add_raw_templates(vec![ + ("base", std::str::from_utf8(&base_html.data).unwrap()), + ("index", std::str::from_utf8(&index_html.data).unwrap()), + ( + "pretty", + std::str::from_utf8(&pretty_html.data).unwrap(), + ), + ]) + .expect("Could not add raw templates to the tera instance"); +} + /// A minimal, opinionated pastebin #[derive(Parser, Debug)] #[clap(author, version, about, long_about=None)] @@ -22,7 +45,7 @@ pub struct Args { port: u16, /// Address on which the webserver runs - #[clap(short, long, default_value = "0.0.0.0")] + #[clap(short, long, default_value = "127.0.0.1")] address: IpAddr, /// Binary uploads file size limit (in MiB) @@ -40,14 +63,21 @@ pub fn get_upload_dir() -> PathBuf { #[launch] fn rocket() -> _ { - let shield = Shield::default().disable::(); let args = get_parsed_args(); + // Custom Fairings and Providers + let shield = Shield::default().disable::(); + let figment = Figment::from(rocket::Config::default()) + .merge(("port", args.port)) + .merge(("address", args.address)) + .merge(("template_dir", ".")) // Required if embedding templates + .merge(Env::prefixed("BIN_").global()); + // create the upload directory, if not already created fs::create_dir_all(args.upload) .expect("Could not create the upload directory"); - rocket::build() + rocket::custom(figment) .mount( "/", routes![ @@ -62,5 +92,7 @@ fn rocket() -> _ { ], ) .attach(shield) - .attach(Template::fairing()) + .attach(Template::custom(|engines| { + setup_tera_engine(&mut engines.tera) + })) }