Is there a reason you don't use tower_http::services::ServeDir to serve the files? I don't think your get_file method is safe as the path can contain ../ segments, which would allow somebody to read arbitrary files from your server.
Once you get your endpoint working, try calling it with variations on file=../etc/passwd, file=../../etc/passwd, and so on. You've written a fairly classic path traversal vulnerability, and someone can use this to read any file on the host that the server has read access to (which is a lot).
The standard fix is to normalize the path, which resolves any relative path segments, symbolic links, and so on, leaving only the final path to the target file, and then to check that that path is within the directory or directories you intend to provide access to. In a case like this, where you're serving everything that's in files/, you can use this hander to do the work, too.
You can return Json<T> to have Axum automatically handle the encoding and headers for you:
async fn get_file(Path(name): Path<String>) -> Json<FileResp> {
let file_name = todo!();
let content = std::fs::read_to_string(file_name).unwrap_or_default();
Json(FileResp { content })
}
[package]
name = "baiguoname-hello-world"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
axum = "0.7.5"
serde = { version = "1.0.203", features = ["derive"] }
tokio = { version = "1.38.0", features = ["rt", "rt-multi-thread"] }
% curl -v http://localhost:8081/files/example
* Host localhost:8081 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:8081...
* Connected to localhost (::1) port 8081
> GET /files/example HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/8.7.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< content-type: application/json
< content-length: 21
< date: Sun, 30 Jun 2024 15:22:09 GMT
<
* Connection #0 to host localhost left intact
{"content":"example"}
Note the content-type header on the response, which is application/json as desired.
Can you post something runnable that demonstrates the behaviour?