diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml index 014db91..b28a650 100644 --- a/.github/workflows/container.yml +++ b/.github/workflows/container.yml @@ -1,4 +1,6 @@ name: Docker Container Build +permissions: + contents: read on: pull_request: diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bf8bfe8..1c80a7c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,4 +1,6 @@ name: Backend Checks +permissions: + contents: read on: push: diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..0e2a587 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +## 0.2.0 - 2026-03-15 + +### Added + +- Added MAX_URI_LENGTH as an environment variable to limit expected length to redirect to HTTPS. + +### Changed + +- Max URI length is now enforced by default for https redirection. Current default is set to 2048 characters, and can be extended further if needed via the MAX_URI_LENGTH environment variable. +- HTTPS Redirection now uses the HTTPS_REDIRECT_HOST environment variable to determine the domain name to redirect to rather than the URL. \ No newline at end of file diff --git a/README.md b/README.md index eb2c13c..6d31aa6 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,22 @@ Simple docker image to serve static files over HTTP and optionally redirect to HTTPS ## Usage + +### Setup + TODO +### Configuration + +This image is configured via the following environment variables: + +| Variable | Description | +|---------------------|--------------------------------------------------------------------------------------------------------------------------------------------| +| MOUNT_PATH | The root URL for serving files from. | +| SERVE_FROM | The path to the folder on the disk which the files are located in. | +| HTTPS_REDIRECT_HOST | Domain name to redirect to with HTTPS redirect. If set and non-empty the container will redirect to HTTPS, regardless of current protocol. | +| MAX_URI_CHARACTERS | The maximum length of the URI, in characters, to redirect to HTTPS. Anything over this limit will receive an HTTP 400 Bad Request. | + ## Contributing To enable the pre-commit hook which can run the pipeline checks locally before making a PR, run ```git config core.hooksPath .githooks``` diff --git a/src/main.rs b/src/main.rs index aa8ecd7..1038222 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ use actix_web::web::Redirect; -use actix_web::{App, HttpRequest, HttpServer, Responder, guard, web}; +use actix_web::{guard, web, App, HttpRequest, HttpServer, Responder}; use std::env; +const DEFAULT_MAX_URI_CHARS: usize = 2048; + #[actix_web::main] async fn main() -> std::io::Result<()> { let server = HttpServer::new(move || App::new().configure(configure)); @@ -23,18 +25,34 @@ fn configure(cfg: &mut web::ServiceConfig) { ); } - if let Ok(allow_redirect) = env::var("REDIRECT_TO_HTTPS") - && !allow_redirect.is_empty() + if let Ok(https_redirect_host) = env::var("HTTPS_REDIRECT_HOST") + && !https_redirect_host.is_empty() { - cfg.default_service(web::route().to(https_redirect_handler)); + let max_uri_length = env::var("MAX_URI_CHARACTERS").map( + |max_uri_length| max_uri_length.parse::().unwrap_or(DEFAULT_MAX_URI_CHARS) + ).unwrap_or(DEFAULT_MAX_URI_CHARS); + cfg.default_service(web::route().to(move |request| + https_redirect_handler(request, max_uri_length) + )); } } -async fn https_redirect_handler(request: HttpRequest) -> impl Responder { +async fn https_redirect_handler( + request: HttpRequest, + max_uri_length: usize, +) -> actix_web::Result { + let host = match env::var("HTTPS_REDIRECT_HOST") { + Ok(host) => host, + Err(_) => return Err(actix_web::error::ErrorInternalServerError("HTTPS_REDIRECT_HOST not set")), + }; + let path = request.uri().path(); + if 8 + host.chars().count() + path.chars().count() > max_uri_length { + return Err(actix_web::error::ErrorBadRequest("URI too long")); + } let target_url = format!( "https://{}{}", - request.connection_info().host(), - request.uri().path() + host, + path ); - Redirect::to(target_url).permanent() + Ok(Redirect::to(target_url).permanent()) }