diff options
author | Sven-Hendrik Haase <svenstaro@gmail.com> | 2025-03-07 01:15:43 +0000 |
---|---|---|
committer | Sven-Hendrik Haase <svenstaro@gmail.com> | 2025-03-07 01:15:43 +0000 |
commit | dfdd2456a906b177efad17e52fb9fd971764c5c4 (patch) | |
tree | f27e0a735ad420e8b83da18c602cc3dc2cba9c32 | |
parent | Document ?raw=true (diff) | |
download | miniserve-dfdd2456a906b177efad17e52fb9fd971764c5c4.tar.gz miniserve-dfdd2456a906b177efad17e52fb9fd971764c5c4.zip |
Add healthcheck route at /__miniserve_internal/healthcheck
Fixes #1435
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | src/config.rs | 20 | ||||
-rw-r--r-- | src/main.rs | 5 | ||||
-rw-r--r-- | tests/serve_request.rs | 19 |
4 files changed, 38 insertions, 7 deletions
@@ -143,6 +143,7 @@ Some mobile browsers like Firefox on Android will offer to open the camera app w - Supports README.md rendering like on GitHub - Range requests - WebDAV support +- Healthcheck route (at `/__miniserve_internal/healthcheck`) ## Usage diff --git a/src/config.rs b/src/config.rs index 379f7a7..7d491c4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -63,10 +63,13 @@ pub struct MiniserveConfig { /// Route prefix; Either empty or prefixed with slash pub route_prefix: String, - /// Randomly generated favicon route + /// Well-known healthcheck route (prefixed if route_prefix is provided) + pub healthcheck_route: String, + + /// Well-known favicon route (prefixed if route_prefix is provided) pub favicon_route: String, - /// Randomly generated css route + /// Well-known css route (prefixed if route_prefix is provided) pub css_route: String, /// Default color scheme @@ -198,19 +201,21 @@ impl MiniserveConfig { } } - // Generate some random routes for the favicon and css so that they are very unlikely to conflict with - // real files. - // If --random-route is enabled , in order to not leak the random generated route, we must not use it + // Format some well-known routes at paths that are very unlikely to conflict with real + // files. + // If --random-route is enabled, in order to not leak the random generated route, we must not use it // as static files prefix. // Otherwise, we should apply route_prefix to static files. - let (favicon_route, css_route) = if args.random_route { + let (healthcheck_route, favicon_route, css_route) = if args.random_route { ( + "/__miniserve_internal/healthcheck".into(), "/__miniserve_internal/favicon.svg".into(), "/__miniserve_internal/style.css".into(), ) } else { ( - format!("{}/{}", route_prefix, "__miniserve_internal/favicon.ico"), + format!("{}/{}", route_prefix, "__miniserve_internal/healthcheck"), + format!("{}/{}", route_prefix, "__miniserve_internal/favicon.svg"), format!("{}/{}", route_prefix, "__miniserve_internal/style.css"), ) }; @@ -299,6 +304,7 @@ impl MiniserveConfig { default_sorting_method: args.default_sorting_method, default_sorting_order: args.default_sorting_order, route_prefix, + healthcheck_route, favicon_route, css_route, default_color_scheme, diff --git a/src/main.rs b/src/main.rs index ccf611c..688aed1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -219,6 +219,7 @@ async fn run(miniserve_config: MiniserveConfig) -> Result<(), StartupError> { miniserve_config.compress_response, middleware::Compress::default(), )) + .route(&inside_config.healthcheck_route, web::get().to(healthcheck)) .route(&inside_config.favicon_route, web::get().to(favicon)) .route(&inside_config.css_route, web::get().to(css)) .service( @@ -429,6 +430,10 @@ async fn error_404(req: HttpRequest) -> Result<HttpResponse, RuntimeError> { Err(RuntimeError::RouteNotFoundError(req.path().to_string())) } +async fn healthcheck() -> impl Responder { + HttpResponse::Ok().body("OK") +} + async fn favicon() -> impl Responder { let logo = include_str!("../data/logo.svg"); HttpResponse::Ok() diff --git a/tests/serve_request.rs b/tests/serve_request.rs index f840efd..2910074 100644 --- a/tests/serve_request.rs +++ b/tests/serve_request.rs @@ -73,6 +73,25 @@ fn serves_requests_with_non_default_port(server: TestServer) -> Result<(), Error } #[rstest] +#[case("__miniserve_internal/healthcheck", server(None::<&str>))] +#[case("__miniserve_internal/favicon.svg", server(None::<&str>))] +#[case("__miniserve_internal/style.css", server(None::<&str>))] +#[case("testlol/__miniserve_internal/healthcheck", server(&["--route-prefix", "testlol"]))] +#[case("testlol/__miniserve_internal/favicon.svg", server(&["--route-prefix", "testlol"]))] +#[case("testlol/__miniserve_internal/style.css", server(&["--route-prefix", "testlol"]))] +#[case("__miniserve_internal/healthcheck", server(&["--random-route"]))] +#[case("__miniserve_internal/favicon.svg", server(&["--random-route"]))] +#[case("__miniserve_internal/style.css", server(&["--random-route"]))] +fn serves_requests_for_special_routes( + #[case] route: &str, + #[case] server: TestServer, +) -> Result<(), Error> { + let body = reqwest::blocking::get(format!("{}{}", server.url(), route))?.error_for_status()?; + + Ok(()) +} + +#[rstest] fn serves_requests_hidden_files(#[with(&["--hidden"])] server: TestServer) -> Result<(), Error> { let body = reqwest::blocking::get(server.url())?.error_for_status()?; let parsed = Document::from_read(body)?; |