feat(http): enhance path handling

- Add global route map to store static routes.
- Match parent path to find route in route map.
This commit is contained in:
xfy
2025-04-10 10:40:45 +08:00
parent 1fe812ef4c
commit 14cdf3b35d
4 changed files with 29 additions and 20 deletions

View File

@ -38,12 +38,6 @@ pub struct SettingRoute {
/// Host routes
/// Each host can have multiple routes
pub type HostRouteMap = BTreeMap<String, SettingRoute>;
pub fn host_route_map(routes: Vec<SettingRoute>) -> HostRouteMap {
routes
.into_iter()
.map(|route| (route.location.clone(), route))
.collect()
}
/// Virtual host
/// Each host can listen on one port and one ip

View File

@ -1,13 +1,13 @@
use std::time::Duration;
use std::{collections::BTreeMap, sync::LazyLock, time::Duration};
use axum::{Router, middleware, routing::get};
use tokio::net::TcpListener;
use tokio::{net::TcpListener, sync::RwLock};
use tower::ServiceBuilder;
use tower_http::timeout::TimeoutLayer;
use tracing::{debug, info, warn};
use crate::{
config::SettingHost,
config::{HostRouteMap, SettingHost},
middlewares::{add_version, logging_route},
utils::{shutdown, shutdown_signal},
};
@ -15,6 +15,11 @@ use crate::{
pub mod error;
pub mod serve;
/// Static route map
/// Use host_route.location as key
/// Use host_route as value
static ROUTE_MAP: LazyLock<RwLock<HostRouteMap>> = LazyLock::new(|| RwLock::new(BTreeMap::new()));
pub async fn make_server(host: SettingHost) -> anyhow::Result<()> {
let mut router = Router::new();
// find routes in config
@ -41,11 +46,14 @@ pub async fn make_server(host: SettingHost) -> anyhow::Result<()> {
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));
// }
{
let path = if host_route.location.ends_with('/') {
host_route.location.clone()
} else {
format!("{}/", host_route.location)
};
ROUTE_MAP.write().await.insert(path, host_route.clone());
}
}
router = router.layer(

View File

@ -2,6 +2,8 @@ use axum::{extract::Path, response::IntoResponse};
use http::Uri;
use tracing::debug;
use crate::http::{ROUTE_MAP, error::RouteError};
use super::error::RouteResult;
/// Serve static files
@ -19,7 +21,14 @@ pub async fn serve(uri: Uri, Path(path): Path<String>) -> RouteResult<impl IntoR
let uri_path = uri.path();
let parent_path = uri_path.get(0..uri_path.len() - path.len());
let parent_path = parent_path.unwrap_or("/");
// parent_path is key in route map
// which is `host_route.location`
debug!("request: {:?} uri {}", path, parent_path);
let route_map = ROUTE_MAP.read().await;
let Some(host_route) = route_map.get(parent_path) else {
return Err(RouteError::Any(anyhow::anyhow!("route not found")));
};
debug!("route: {:?}", host_route);
// let host_route = app
// .host_route
// .get(&request.uri().path().to_string())

View File

@ -44,12 +44,10 @@ async fn main() -> Result<()> {
info!("{}", COMPILER);
info!("OS: {} {}", OS, ARCH);
// let hosts = settings.host.clone();
let mut servers = settings
.host
.into_iter()
.map(make_server)
.collect::<JoinSet<_>>();
let hosts = settings.host;
let mut servers = hosts.into_iter().map(make_server).collect::<JoinSet<_>>();
// settings.host = vec![];
info!("server started");