From d445b78f96d95bc12f124e82751ba950dedf6281 Mon Sep 17 00:00:00 2001 From: sigoden Date: Mon, 28 Oct 2024 07:37:21 +0800 Subject: [PATCH] feat: provide healthcheck API (#474) --- README.md | 10 +++++++++- src/server.rs | 11 +++++++++-- tests/health.rs | 31 +++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 tests/health.rs diff --git a/README.md b/README.md index 1456c1d..dad7dfd 100644 --- a/README.md +++ b/README.md @@ -216,8 +216,14 @@ dd skip=$upload_offset if=file status=none ibs=1 | \ curl -X PATCH -H "X-Update-Range: append" --data-binary @- http://127.0.0.1:5000/file ``` +Health checks + +```sh +curl http://127.0.0.1:5000/__dufs__/health +``` +
-

Advanced topics

+

Advanced Topics

### Access Control @@ -395,6 +401,8 @@ Dufs allows users to customize the UI with your own assets. dufs --assets my-assets-dir/ ``` +> If you only need to make slight adjustments to the current UI, you copy dufs's [assets](https://github.com/sigoden/dufs/tree/main/assets) directory and modify it accordingly. The current UI doesn't use any frameworks, just plain HTML/JS/CSS. As long as you have some basic knowledge of web development, it shouldn't be difficult to modify. + Your assets folder must contains a `index.html` file. `index.html` can use the following placeholder variables to retrieve internal data. diff --git a/src/server.rs b/src/server.rs index 3aa172d..5c404ca 100644 --- a/src/server.rs +++ b/src/server.rs @@ -62,6 +62,7 @@ const INDEX_NAME: &str = "index.html"; const BUF_SIZE: usize = 65536; const EDITABLE_TEXT_MAX_SIZE: u64 = 4194304; // 4M const RESUMABLE_UPLOAD_MIN_SIZE: u64 = 20971520; // 20M +const HEALTH_CHECK_PATH: &str = "__dufs__/health"; pub struct Server { args: Args, @@ -171,7 +172,7 @@ impl Server { if method == Method::GET && self - .handle_assets(&relative_path, headers, &mut res) + .handle_internal(&relative_path, headers, &mut res) .await? { return Ok(res); @@ -738,7 +739,7 @@ impl Server { Ok(()) } - async fn handle_assets( + async fn handle_internal( &self, req_path: &str, headers: &HeaderMap, @@ -789,6 +790,12 @@ impl Server { HeaderValue::from_static("nosniff"), ); Ok(true) + } else if req_path == HEALTH_CHECK_PATH { + res.headers_mut() + .typed_insert(ContentType::from(mime_guess::mime::APPLICATION_JSON)); + + *res.body_mut() = body_full(r#"{"status":"OK"}"#); + Ok(true) } else { Ok(false) } diff --git a/tests/health.rs b/tests/health.rs new file mode 100644 index 0000000..56d4f5b --- /dev/null +++ b/tests/health.rs @@ -0,0 +1,31 @@ +mod fixtures; +mod utils; + +use fixtures::{server, Error, TestServer}; +use rstest::rstest; + +const HEALTH_CHECK_PATH: &str = "__dufs__/health"; +const HEALTH_CHECK_RESPONSE: &str = r#"{"status":"OK"}"#; + +#[rstest] +fn normal_health(server: TestServer) -> Result<(), Error> { + let resp = reqwest::blocking::get(format!("{}{HEALTH_CHECK_PATH}", server.url()))?; + assert_eq!(resp.text()?, HEALTH_CHECK_RESPONSE); + Ok(()) +} + +#[rstest] +fn auth_health( + #[with(&["--auth", "user:pass@/:rw", "-A"])] server: TestServer, +) -> Result<(), Error> { + let resp = reqwest::blocking::get(format!("{}{HEALTH_CHECK_PATH}", server.url()))?; + assert_eq!(resp.text()?, HEALTH_CHECK_RESPONSE); + Ok(()) +} + +#[rstest] +fn path_prefix_health(#[with(&["--path-prefix", "xyz"])] server: TestServer) -> Result<(), Error> { + let resp = reqwest::blocking::get(format!("{}xyz/{HEALTH_CHECK_PATH}", server.url()))?; + assert_eq!(resp.text()?, HEALTH_CHECK_RESPONSE); + Ok(()) +}