Skip to content

Commit f0b0a7f

Browse files
committed
http serve 功能开发完成
1 parent 34e12d9 commit f0b0a7f

File tree

1 file changed

+61
-17
lines changed

1 file changed

+61
-17
lines changed

src/process/http_serve.rs

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
use anyhow::Result;
22
use axum::{
3-
extract::{Path, State},
4-
http::StatusCode,
5-
routing::get,
6-
Router,
3+
extract::{Path, State}, http::StatusCode, response::{Html, IntoResponse}, routing::get, Router
74
};
85
use std::{net::SocketAddr, path::PathBuf, sync::Arc};
96
use tower_http::services::ServeDir;
@@ -30,35 +27,82 @@ pub async fn process_http_serve(path: PathBuf, port: u16) -> Result<()> {
3027
Ok(())
3128
}
3229

30+
fn is_dir(path: &std::path::Path) -> bool {
31+
match std::fs::metadata(path) {
32+
Ok(metadata) => metadata.is_dir(),
33+
Err(_) => false,
34+
}
35+
}
36+
37+
fn remove_dir(path: String, dir: String) -> String {
38+
if path.starts_with(&dir) {
39+
// 如果字符串以指定前缀开头,则通过切片去除前缀
40+
path[dir.len()..].to_owned()
41+
} else {
42+
// 如果字符串不以指定前缀开头,则返回原始字符串
43+
path
44+
}
45+
}
46+
3347
async fn file_handler(
3448
State(state): State<Arc<HttpServeState>>,
3549
Path(path): Path<String>,
36-
) -> (StatusCode, String) {
50+
) -> (StatusCode, impl IntoResponse) {
3751
let p = std::path::Path::new(&state.path).join(path);
3852
info!("Reading file {:?}", p);
3953
if !p.exists() {
4054
(
4155
StatusCode::NOT_FOUND,
42-
format!("File {} note found", p.display()),
56+
format!("File {} note found", p.display()).into_response(),
4357
)
4458
} else {
45-
// TODO: test p is a directory
46-
// if it is a directory, list all files/subdirectories
47-
// as <li><a href="/path/to/file">file name</a></li>
48-
// <html><body><ul>...</ul></body></html>
49-
match tokio::fs::read_to_string(p).await {
50-
Ok(content) => {
51-
info!("Read {} bytes", content.len());
52-
(StatusCode::OK, content)
59+
if is_dir(&p) {
60+
let mut entries = tokio::fs::read_dir(p).await.unwrap();
61+
let mut content = "".to_string();
62+
while let Some(entry) = entries.next_entry().await.unwrap() {
63+
let path = entry.path();
64+
content.push_str(&format!(
65+
"<li><a href=\"\\{}\">{}</a></li>\n",
66+
remove_dir(path.display().to_string(), state.path.display().to_string()),
67+
path.file_name().unwrap().to_str().unwrap().to_owned(),
68+
));
5369
}
54-
Err(e) => {
55-
warn!("Error reading file: {:?}", e);
56-
(StatusCode::INTERNAL_SERVER_ERROR, e.to_string())
70+
71+
//content = format!("<html><body><ul>{}</ul></body></html>", content);
72+
content = format!(
73+
r#"
74+
<!DOCTYPE html>
75+
<html>
76+
<head>
77+
<meta charset="utf-8">
78+
<title>http server</title>
79+
</head>
80+
<body>
81+
<ul>{}</ul>
82+
</body>
83+
</html>"#,
84+
content
85+
);
86+
(StatusCode::OK, Html(content).into_response())
87+
} else {
88+
match tokio::fs::read_to_string(p).await {
89+
Ok(content) => {
90+
info!("Read {} bytes", content.len());
91+
(StatusCode::OK, content.into_response())
92+
}
93+
Err(e) => {
94+
warn!("Error reading file: {:?}", e);
95+
(
96+
StatusCode::INTERNAL_SERVER_ERROR,
97+
e.to_string().into_response(),
98+
)
99+
}
57100
}
58101
}
59102
}
60103
}
61104

105+
62106
#[cfg(test)]
63107
mod tests {
64108
use super::*;

0 commit comments

Comments
 (0)