diff options
author | Sven-Hendrik Haase <svenstaro@gmail.com> | 2023-08-07 13:46:03 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-07 13:46:03 +0000 |
commit | e3c0abb309ca8b2995072e541a9b7c6a8790fe8f (patch) | |
tree | c238f73a08f05f284e36ad5ed8721d7aa3fb0c82 | |
parent | Merge pull request #1192 from svenstaro/dependabot/cargo/serde-1.0.181 (diff) | |
parent | Adjust from feedback (diff) | |
download | miniserve-e3c0abb309ca8b2995072e541a9b7c6a8790fe8f.tar.gz miniserve-e3c0abb309ca8b2995072e541a9b7c6a8790fe8f.zip |
Merge pull request #1193 from nlopes/nlopes-pretty-urls
Add pretty urls
-rw-r--r-- | src/args.rs | 8 | ||||
-rw-r--r-- | src/config.rs | 8 | ||||
-rw-r--r-- | src/main.rs | 29 | ||||
-rw-r--r-- | tests/serve_request.rs | 18 |
4 files changed, 62 insertions, 1 deletions
diff --git a/src/args.rs b/src/args.rs index f7b42f1..590ac14 100644 --- a/src/args.rs +++ b/src/args.rs @@ -41,6 +41,14 @@ pub struct CliArgs { #[arg(long, requires = "index", env = "MINISERVE_SPA")] pub spa: bool, + /// Activate Pretty URLs mode + /// + /// This will cause the server to serve the equivalent `.html` file indicated by the path. + /// + /// `/about` will try to find `about.html` and serve it. + #[arg(long, env = "MINISERVE_PRETTY_URLS")] + pub pretty_urls: bool, + /// Port to use #[arg( short = 'p', diff --git a/src/config.rs b/src/config.rs index 8976d35..2df9fdd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -80,6 +80,13 @@ pub struct MiniserveConfig { /// allow the SPA router to handle the request instead. pub spa: bool, + /// Activate Pretty URLs mode + /// + /// This will cause the server to serve the equivalent `.html` file indicated by the path. + /// + /// `/about` will try to find `about.html` and serve it. + pub pretty_urls: bool, + /// Enable QR code display pub show_qrcode: bool, @@ -250,6 +257,7 @@ impl MiniserveConfig { default_color_scheme_dark, index: args.index, spa: args.spa, + pretty_urls: args.pretty_urls, overwrite_files: args.overwrite_files, show_qrcode: args.qrcode, mkdir_enabled: args.mkdir_enabled, diff --git a/src/main.rs b/src/main.rs index 851f9ab..78e8472 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,9 @@ use std::time::Duration; use actix_files::NamedFile; use actix_web::{ - http::header::ContentType, middleware, web, App, HttpRequest, HttpResponse, Responder, + dev::{fn_service, ServiceRequest, ServiceResponse}, + http::header::ContentType, + middleware, web, App, HttpRequest, HttpResponse, Responder, }; use actix_web_httpauth::middleware::HttpAuthentication; use anyhow::Result; @@ -316,6 +318,31 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) { } } + // Handle --pretty-urls options. + // + // We rewrite the request to append ".html" to the path and serve the file. If the + // path ends with a `/`, we remove it before appending ".html". + // + // This is done to allow for pretty URLs, e.g. "/about" instead of "/about.html". + if conf.pretty_urls { + files = files.default_handler(fn_service(|req: ServiceRequest| async { + let (req, _) = req.into_parts(); + let conf = req + .app_data::<MiniserveConfig>() + .expect("Could not get miniserve config"); + let mut path_base = req.path()[1..].to_string(); + if path_base.ends_with('/') { + path_base.pop(); + } + if !path_base.ends_with("html") { + path_base = format!("{}.html", path_base); + } + let file = NamedFile::open_async(conf.path.join(path_base)).await?; + let res = file.into_response(&req); + Ok(ServiceResponse::new(req, res)) + })); + } + if conf.show_hidden { files = files.use_hidden_files(); } diff --git a/tests/serve_request.rs b/tests/serve_request.rs index e717525..ac4360e 100644 --- a/tests/serve_request.rs +++ b/tests/serve_request.rs @@ -268,6 +268,24 @@ fn serve_index_instead_of_404_in_spa_mode( } #[rstest] +#[case(server_no_stderr(&["--pretty-urls", "--index", FILES[1]]), "/")] +#[case(server_no_stderr(&["--pretty-urls", "--index", FILES[1]]), "test.html")] +#[case(server_no_stderr(&["--pretty-urls", "--index", FILES[1]]), "test")] +fn serve_file_instead_of_404_in_pretty_urls_mode( + #[case] server: TestServer, + #[case] url: &str, +) -> Result<(), Error> { + let body = reqwest::blocking::get(format!("{}{}", server.url(), url))?.error_for_status()?; + let parsed = Document::from_read(body)?; + assert!(parsed + .find(|x: &Node| x.text() == "Test Hello Yes") + .next() + .is_some()); + + Ok(()) +} + +#[rstest] #[case(server(&["--route-prefix", "foobar"]))] #[case(server(&["--route-prefix", "/foobar/"]))] fn serves_requests_with_route_prefix(#[case] server: TestServer) -> Result<(), Error> { |