From a88a4ee630d80a21c7b4b480cfcfc1f67a1a80a4 Mon Sep 17 00:00:00 2001 From: sigoden Date: Thu, 23 Apr 2026 18:39:26 +0800 Subject: [PATCH] feat: support `?json` on file path (#686) --- src/server.rs | 29 ++++++++++++++++++++++++++++- tests/http.rs | 16 ++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/server.rs b/src/server.rs index 8eef53a..fe2d672 100644 --- a/src/server.rs +++ b/src/server.rs @@ -351,7 +351,9 @@ impl Server { .await?; } } else if is_file { - if has_query_flag(&query_params, "edit") { + if has_query_flag(&query_params, "json") { + self.handle_file_json(path, head_only, &mut res).await?; + } else if has_query_flag(&query_params, "edit") { self.handle_edit_file(path, DataKind::Edit, head_only, user, &mut res) .await?; } else if has_query_flag(&query_params, "view") { @@ -723,6 +725,31 @@ impl Server { Ok(()) } + async fn handle_file_json( + &self, + path: &Path, + head_only: bool, + res: &mut Response, + ) -> Result<()> { + let pathitem = match self.to_pathitem(path, &self.args.serve_path).await? { + Some(v) => v, + None => { + status_not_found(res); + return Ok(()); + } + }; + let output = serde_json::to_string_pretty(&pathitem)?; + res.headers_mut() + .typed_insert(ContentType::from(mime_guess::mime::APPLICATION_JSON)); + res.headers_mut() + .typed_insert(ContentLength(output.len() as u64)); + if head_only { + return Ok(()); + } + *res.body_mut() = body_full(output); + Ok(()) + } + async fn handle_render_spa( &self, path: &Path, diff --git a/tests/http.rs b/tests/http.rs index df16a92..c46667e 100644 --- a/tests/http.rs +++ b/tests/http.rs @@ -185,6 +185,22 @@ fn get_file(server: TestServer) -> Result<(), Error> { Ok(()) } +#[rstest] +fn get_file_json(server: TestServer) -> Result<(), Error> { + let resp = reqwest::blocking::get(format!("{}index.html?json", server.url()))?; + assert_eq!(resp.status(), 200); + assert_eq!( + resp.headers().get("content-type").unwrap(), + "application/json" + ); + let json: Value = serde_json::from_str(&resp.text()?).unwrap(); + assert_eq!(json["name"], "index.html"); + assert_eq!(json["path_type"], "File"); + assert!(json["size"].as_u64().is_some()); + assert!(json["mtime"].as_u64().is_some()); + Ok(()) +} + #[rstest] fn head_file(server: TestServer) -> Result<(), Error> { let resp = fetch!(b"HEAD", format!("{}index.html", server.url())).send()?;