From 6127f2a90cc810d586cc59b7129a810328ea668f Mon Sep 17 00:00:00 2001 From: spikecodes <19519553+spikecodes@users.noreply.github.com> Date: Sat, 16 Jan 2021 22:04:03 -0800 Subject: [PATCH] Support forced HTTPS redirects #39 --- Cargo.lock | 13 +++++++++++++ Cargo.toml | 1 + README.md | 2 ++ src/main.rs | 27 +++++++++++++++++++++------ 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa1965a..c14a969 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -684,6 +684,7 @@ checksum = "da9052a1a50244d8d5aa9bf55cbc2fb6f357c86cc52e46c62ed390a7180cf150" dependencies = [ "futures-channel", "futures-core", + "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -706,6 +707,17 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79e5145dde8da7d1b3892dad07a9c98fc04bc39892b1ecc9692cf53e2b780a65" +[[package]] +name = "futures-executor" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e59fdc009a4b3096bf94f740a0f2424c082521f20a9b08c5c07c48d90fd9b9" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.12" @@ -988,6 +1000,7 @@ dependencies = [ "askama", "async-recursion", "base64 0.13.0", + "futures", "regex", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index e501015..d79d1d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ edition = "2018" [dependencies] base64 = "0.13.0" actix-web = { version = "3.3.2", features = ["rustls"] } +futures = "0.3" askama = "0.10.5" ureq = "2.0.1" serde = { version = "1.0.118", default_features = false, features = ["derive"] } diff --git a/README.md b/README.md index 8576775..a519bcd 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,8 @@ Specify a custom address for the server by passing the `-a` or `--address` argum libreddit --address=0.0.0.0:8111 ``` +Given you have a TLS certificate, you can pass the `-r` or `--redirect-https` arguments to force HTTPS. + ## Building ``` diff --git a/src/main.rs b/src/main.rs index 87d302f..2d10985 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ // Import Crates -use actix_web::{middleware, web, App, HttpResponse, HttpServer}; // dev::Service +use actix_web::{App, HttpResponse, HttpServer, dev::{Service, ServiceResponse}, middleware, web}; +use futures::future::FutureExt; // Reference local files mod post; @@ -30,12 +31,12 @@ async fn favicon() -> HttpResponse { #[actix_web::main] async fn main() -> std::io::Result<()> { let mut address = "0.0.0.0:8080".to_string(); - // let mut https = false; + let mut force_https = false; for arg in std::env::args().collect::>() { match arg.split('=').collect::>()[0] { "--address" | "-a" => address = arg.split('=').collect::>()[1].to_string(), - // "--redirect-https" | "-r" => https = true, + "--redirect-https" | "-r" => force_https = true, _ => (), } } @@ -43,10 +44,24 @@ async fn main() -> std::io::Result<()> { // start http server println!("Running Libreddit v{} on {}!", env!("CARGO_PKG_VERSION"), &address); - HttpServer::new(|| { + HttpServer::new(move || { App::new() - // Redirect to HTTPS - // .wrap_fn(|req, srv| { let fut = srv.call(req); async { let mut res = fut.await?; if https {} Ok(res) } }) + // Redirect to HTTPS if "--redirect-https" enabled + .wrap_fn(move |req, srv| { + let secure = req.connection_info().scheme() == "https"; + let https_url = format!("https://{}{}", req.connection_info().host(), req.uri().to_string()); + srv.call(req).map(move |res: Result | { + if force_https && !secure { + let redirect: ServiceResponse = ServiceResponse::new( + res.unwrap().request().clone(), + HttpResponse::Found().header("Location", https_url).finish() + ); + Ok(redirect) + } else { + res + } + }) + }) // Append trailing slash and remove double slashes .wrap(middleware::NormalizePath::default()) // Default service in case no routes match