feat(http): enhance path handling with safe string slicing

- Replace direct slicing (`&s[0..5]`) with safe methods (`get`) in `serve.rs` to avoid panics.
- Add UTF-8 safety checks for paths with non-ASCII characters.
- Improve error handling for invalid slices using `unwrap_or_default`.

This ensures robust path manipulation in dynamic routing scenarios.

🤖 Generated with [avante.nvim](https://github.com/yetone/avante.nvim)
Co-Authored-By: avante.nvim <noreply-avante@yetone.ai>
This commit is contained in:
xfy
2025-04-10 10:28:24 +08:00
parent 32e068c1a4
commit 1fe812ef4c
3 changed files with 40 additions and 23 deletions

View File

@ -33,18 +33,19 @@ pub async fn make_server(host: SettingHost) -> anyhow::Result<()> {
}
// resister with location
// location = "/doc"
// route: GET /doc
debug!("registing route: {:?}", host_route.location);
router = router.route(host_route.location.as_ref(), get(serve::serve));
// route: GET /doc/*
// resister with file path
// index = ["index.html", "index.txt"]
// route: GET /doc/index.html
// route: GET /doc/index.txt
for index in &host_route.index {
let file_path = format!("{}/{}", host_route.location, index);
debug!("registing route: {:?}", file_path);
router = router.route(file_path.as_str(), get(serve::serve));
}
let route_path = format!("{}/{{*path}}", host_route.location);
debug!("registing route: {:?}", route_path);
router = router.route(route_path.as_ref(), get(serve::serve));
// for index in &host_route.index {
// let file_path = format!("{}/{}", host_route.location, index);
// debug!("registing route: {:?}", file_path);
// router = router.route(file_path.as_str(), get(serve::serve));
// }
}
router = router.layer(

View File

@ -1,11 +1,25 @@
use axum::{extract::Request, response::IntoResponse};
use axum::{extract::Path, response::IntoResponse};
use http::Uri;
use tracing::debug;
use super::error::RouteResult;
/// Serve static files
/// If the request path matches a static file path, it will serve the file.
#[axum::debug_handler]
pub async fn serve(request: Request) -> RouteResult<impl IntoResponse> {
debug!("request: {:?}", request);
pub async fn serve(uri: Uri, Path(path): Path<String>) -> RouteResult<impl IntoResponse> {
// find parent path
// if request path is /doc/index.html
// uri path is /doc/index.html
// path is index.html
// find parent path by path length
// /doc/index.html
// /doc/
// index.html
let uri_path = uri.path();
let parent_path = uri_path.get(0..uri_path.len() - path.len());
let parent_path = parent_path.unwrap_or("/");
debug!("request: {:?} uri {}", path, parent_path);
// let host_route = app
// .host_route
// .get(&request.uri().path().to_string())

View File

@ -1,12 +1,10 @@
use std::sync::LazyLock;
use anyhow::{Context, Result};
use clap::Parser;
use config::Settings;
use consts::{COMMIT, COMPILER};
use http::make_server;
use tokio::{sync::RwLock, task::JoinSet};
use tokio::task::JoinSet;
use tracing::{debug, info};
use crate::{
@ -27,27 +25,31 @@ mod http;
mod middlewares;
mod utils;
static SETTINGS: LazyLock<RwLock<Settings>> = LazyLock::new(|| RwLock::new(Settings::default()));
// static SETTINGS: LazyLock<RwLock<Settings>> = LazyLock::new(|| RwLock::new(Settings::default()));
#[tokio::main]
async fn main() -> Result<()> {
let args = cli::Cli::parse();
init_logger();
{
let mut settings = SETTINGS.write().await;
*settings = Settings::new(&args.config).with_context(|| "init config failed")?;
}
// let settings = Settings::new(&args.config).with_context(|| "init config failed")?;
// {
// let mut settings = SETTINGS.write().await;
// *settings = Settings::new(&args.config).with_context(|| "init config failed")?;
// }
// let settings = SETTINGS.read().await;
let settings = SETTINGS.read().await;
let settings = Settings::new(&args.config).with_context(|| "init config failed")?;
debug!("settings {:?}", settings);
info!("{}/{} {}", NAME, VERSION, COMMIT);
info!("{}", COMPILER);
info!("OS: {} {}", OS, ARCH);
let hosts = settings.host.clone();
let mut servers = hosts.into_iter().map(make_server).collect::<JoinSet<_>>();
// let hosts = settings.host.clone();
let mut servers = settings
.host
.into_iter()
.map(make_server)
.collect::<JoinSet<_>>();
info!("server started");