Skip to content

Commit

Permalink
Use PathBuf to load all HTML files in Jinja environment
Browse files Browse the repository at this point in the history
Pass Jinja template as Mutex via app data to all endpoints
  • Loading branch information
dormant-user committed Feb 17, 2024
1 parent a0ce049 commit 467f7c5
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 96 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ base64 = "0.21.7"
sha2 = "0.10.8"
rand = "0.8.5"
fernet = "0.2.1"
minijinja = "1.0.12"
minijinja = { version = "1.0.12", features = ["loader"] }
pyo3 = { version = "0.20.2", features = ["auto-initialize"] }
url = "2.5.0"
itertools = "0.12.1"
Expand Down
37 changes: 0 additions & 37 deletions src/constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ use std::sync::Mutex;

use fernet::Fernet;
use lazy_static::lazy_static;
use minijinja::Environment;

use crate::template;

pub fn get_binary() -> String {
let binary = env::args().next().unwrap();
Expand Down Expand Up @@ -65,40 +62,6 @@ fn generate_key() -> String {
Fernet::generate_key()
}

// fn get_landing(filename: &str) -> String {
// let filepath = Path::new(env!("CARGO_MANIFEST_DIR"))
// .join("src")
// .join("templates")
// .join(filename)
// .into_os_string().into_string().unwrap();
// std::fs::read_to_string(&filepath).unwrap_or_else(|_| String::new())
// }
//
// pub fn jinja_template() -> Mutex<Environment<'static>> {
// let mut env = Environment::new();
// for html in ["landing", "listing", "logout", "session", "unauthorized"] {
// let extract = Path::new(env!("CARGO_MANIFEST_DIR"))
// .join("src")
// .join("templates")
// .join(format!("{}.html", html))
// .into_os_string().into_string().unwrap();
// env.add_template(&html, &std::fs::read_to_string(&extract).unwrap_or_else(|_| String::new())).unwrap();
// }
// let mutex = Mutex::new(env.to_owned());
// mutex
// }

lazy_static! {
pub static ref ENV: Mutex<Environment<'static>> = Mutex::new({
let mut env = Environment::new();
env.add_template("landing", template::LANDING).unwrap();
env.add_template("listing", template::LISTING).unwrap();
env.add_template("logout", template::LOGOUT).unwrap();
env.add_template("session", template::SESSION).unwrap();
env
});
}

lazy_static::lazy_static! {
pub static ref HOST_SERVE: Mutex<HashMap<String, String>> = Mutex::new(HashMap::new());
}
40 changes: 40 additions & 0 deletions src/jinja.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
use std::path::Path;
use std::sync::{Arc, Mutex};

/// Read the content of each file and return it as a String.
///
/// # Arguments
///
/// * `filename` - Filename that has to be read.
///
/// # Returns
///
/// String representation of the file content.
pub fn get_content(filename: &str) -> String {
let filepath = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("src")
.join("templates")
.join(format!("{}.html", filename))
.to_string_lossy()
.to_string();
std::fs::read_to_string(&filepath).unwrap_or_else(|_| String::new())
}

/// Reads all the HTML files in templates directory and loads the content into a Jinja Environment
///
/// # Rendered files
/// - Index page template that is served as HTML response for the root endpoint.
/// - Landing page template that is served as HTML response while streaming videos.
/// - Listing page template that is served as HTML response after successful authentication.
/// - Logout page template that is served as HTML response when the user decides to end the session.
/// - Session page template that is served as HTML response when invalid/expired session tokens are received.
/// - Unauthorized page template that is served as HTML response after failed authentication.
pub fn environment() -> Arc<Mutex<minijinja::Environment<'static>>> {
let mut env = minijinja::Environment::new();
for html in ["landing", "listing", "logout", "session"] {
let content = get_content(&html);
env.add_template_owned(html, content).unwrap();
}
let mutex = Mutex::new(env.to_owned());
Arc::new(mutex)
}
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rand::prelude::SliceRandom;
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};

mod squire;
mod template;
mod jinja;
mod constant;
mod routes;

Expand Down Expand Up @@ -39,8 +39,10 @@ pub async fn start() -> io::Result<()> {
println!("{}", arts.choose(&mut rand::thread_rng()).unwrap());

let config = squire::startup::get_config(args);
let template = jinja::environment();
// Create a dedicated clone, since it will be used within closure
let config_clone = config.clone();
let template_clone = template.clone();
let host = format!("{}:{}", config.video_host, config.video_port);
log::info!("{} [workers:{}] running on http://{} (Press CTRL+C to quit)",
cargo.pkg_name, config.workers, host);
Expand All @@ -51,8 +53,9 @@ pub async fn start() -> io::Result<()> {
*/
let application = move || {
App::new() // Creates a new Actix web application
.wrap(squire::middleware::get_cors(config_clone.website.clone()))
.app_data(web::Data::new(config_clone.clone()))
.app_data(web::Data::new(template_clone.clone()))
.wrap(squire::middleware::get_cors(config_clone.website.clone()))
.wrap(middleware::Logger::default()) // Adds a default logger middleware to the application
.service(routes::basics::health) // Registers a service for handling requests
.service(routes::basics::root)
Expand Down
27 changes: 15 additions & 12 deletions src/routes/auth.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
use std::sync::Arc;
use std::sync::{Arc, Mutex};

use actix_web::{HttpRequest, HttpResponse, web};
use actix_web::cookie::Cookie;
use actix_web::cookie::time::{Duration, OffsetDateTime};
use actix_web::http::StatusCode;
use itertools::Itertools;
use minijinja::context;
use minijinja::{context, Environment};
use serde::Serialize;

use crate::{constant, routes, squire, template};
use crate::{constant, routes, squire, jinja};
use crate::routes::authenticator::AuthToken;

/// Struct for representing a JSON Response with a redirect URL.
Expand All @@ -28,7 +28,7 @@ pub struct DetailError {
/// # Arguments
///
/// * `config` - Configuration data for the application.
/// * `request`: Actix HttpRequest containing information about the incoming request.
/// * `request` - Actix HttpRequest containing information about the incoming request.
#[post("/login")]
pub async fn login(config: web::Data<Arc<squire::settings::Config>>, request: HttpRequest) -> HttpResponse {
let verified = routes::authenticator::verify_login(&request, &config);
Expand Down Expand Up @@ -67,12 +67,13 @@ pub async fn login(config: web::Data<Arc<squire::settings::Config>>, request: Ht
/// # Arguments
///
/// * `config` - Configuration data for the application.
/// * `request`: Actix HttpRequest containing information about the incoming request.
/// * `request` - Actix HttpRequest containing information about the incoming request.
#[get("/logout")]
pub async fn logout(config: web::Data<Arc<squire::settings::Config>>,
environment: web::Data<Arc<Mutex<Environment<'static>>>>,
request: HttpRequest) -> HttpResponse {
let host = request.connection_info().host().to_owned();
let template = constant::ENV.lock().unwrap();
let template = environment.lock().unwrap();
let logout_template = template.get_template("logout").unwrap();
let mut response = HttpResponse::build(StatusCode::OK);
response.content_type("text/html; charset=utf-8");
Expand Down Expand Up @@ -115,9 +116,10 @@ pub async fn logout(config: web::Data<Arc<squire::settings::Config>>,
/// # Arguments
///
/// * `config` - Configuration data for the application.
/// * `request`: Actix HttpRequest containing information about the incoming request.
/// * `request` - Actix HttpRequest containing information about the incoming request.
#[get("/home")]
pub async fn home(config: web::Data<Arc<squire::settings::Config>>,
environment: web::Data<Arc<Mutex<Environment<'static>>>>,
request: HttpRequest) -> HttpResponse {
let auth_response = routes::authenticator::verify_token(&request, &config);
if !auth_response.ok {
Expand All @@ -137,7 +139,7 @@ pub async fn home(config: web::Data<Arc<squire::settings::Config>>,
};
let args = (config.video_source.to_string_lossy().to_string(), file_format.unwrap());
let listing_page = squire::fileio::get_all_stream_content(args);
let template = constant::ENV.lock().unwrap();
let template = environment.lock().unwrap();
let listing = template.get_template("listing").unwrap();

return HttpResponse::build(StatusCode::OK)
Expand All @@ -151,12 +153,13 @@ pub async fn home(config: web::Data<Arc<squire::settings::Config>>,
///
/// # Arguments
///
/// * `request`: Actix HttpRequest containing information about the incoming request.
/// * `request` - Actix HttpRequest containing information about the incoming request.
#[get("/error")]
pub async fn error(request: HttpRequest) -> HttpResponse {
pub async fn error(environment: web::Data<Arc<Mutex<Environment<'static>>>>,
request: HttpRequest) -> HttpResponse {
if let Some(detail) = request.cookie("detail") {
log::info!("Error response for /error: {}", detail.value());
let template = constant::ENV.lock().unwrap();
let template = environment.lock().unwrap();
let session = template.get_template("session").unwrap();
return HttpResponse::build(StatusCode::OK)
.content_type("text/html; charset=utf-8")
Expand All @@ -166,7 +169,7 @@ pub async fn error(request: HttpRequest) -> HttpResponse {
log::info!("Sending unauthorized response for /error");
return HttpResponse::build(StatusCode::OK)
.content_type("text/html; charset=utf-8")
.body(template::UNAUTHORIZED);
.body(jinja::get_content("unauthorized"));
}

/// Constructs an `HttpResponse` for failed `session_token` verification.
Expand Down
7 changes: 3 additions & 4 deletions src/routes/basics.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use actix_web::{HttpRequest, HttpResponse};
use actix_web::http::StatusCode;

use crate::{squire, template};
use crate::{squire, jinja};

/// Handles the health endpoint, returning a JSON response indicating the server is healthy.
///
Expand All @@ -24,14 +24,13 @@ pub async fn health() -> HttpResponse {
///
/// # Returns
///
/// Returns an `HttpResponse` with a status of 200 (OK), content type "text/html; charset=utf-8",
/// and the body containing HTML content from the `template::INDEX`.
/// Returns an `HttpResponse` with the index page as its body.
#[get("/")]
pub async fn root(request: HttpRequest) -> HttpResponse {
// Log the connection using the squire::logger::log_connection function.
squire::logger::log_connection(&request);

HttpResponse::build(StatusCode::OK)
.content_type("text/html; charset=utf-8")
.body(template::INDEX)
.body(jinja::get_content("index"))
}
7 changes: 4 additions & 3 deletions src/routes/video.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::{Arc, Mutex};

use actix_web::{HttpRequest, HttpResponse, web};
use actix_web::http::StatusCode;
use itertools::Itertools;
use minijinja::context;
use minijinja::{context, Environment};
use serde::Deserialize;
use url::form_urlencoded;

Expand Down Expand Up @@ -113,6 +113,7 @@ pub async fn track(config: web::Data<Arc<squire::settings::Config>>,
/// Returns an `HttpResponse` containing the video content or directory listing, or an error response.
#[get("/stream/{video_path:.*}")]
pub async fn stream(config: web::Data<Arc<squire::settings::Config>>,
environment: web::Data<Arc<Mutex<Environment<'static>>>>,
request: HttpRequest, video_path: web::Path<String>) -> HttpResponse {
let auth_response = routes::authenticator::verify_token(&request, &config);
if !auth_response.ok {
Expand All @@ -131,7 +132,7 @@ pub async fn stream(config: web::Data<Arc<squire::settings::Config>>,
// True path of the video file as a String
let __target_str = __target.to_string_lossy().to_string();
let __filename = __target.file_name().unwrap().to_string_lossy().to_string();
let template = constant::ENV.lock().unwrap();
let template = environment.lock().unwrap();
if __target.is_file() {
let landing = template.get_template("landing").unwrap();
let default_values = squire::settings::default_file_formats();
Expand Down
37 changes: 0 additions & 37 deletions src/template.rs

This file was deleted.

File renamed without changes.
File renamed without changes.

0 comments on commit 467f7c5

Please sign in to comment.