Rust Poem OpenAPI多段路径匹配:单处理器适配可变路径段
解决poem::openapi路径匹配多段namespace的问题
要让处理器同时匹配/mynamespace/myid和/mynamespace/mydomain/myid这类路径,将任意前置路径段存入namespace、最后一段存入id,可以借助poem的通配符路径捕获结合手动拆分路径的方式实现,同时保留SharedHandle的使用。
步骤1:修改路由路径定义
将原有的#[oai(path = "/:namespace/:id", method = "get")]替换为通配符路径,捕获完整的路径内容:
#[oai(path = "/*full_path", method = "get")]
这里的*full_path会捕获请求URL中域名后的所有路径段(不包含开头的/)。
步骤2:在处理器中拆分路径
在处理函数内,将捕获到的full_path按/分割,提取最后一段作为id,剩余部分拼接为namespace,同时保留对SharedHandle的访问:
use poem::{error::BadRequest, web::Path, Json}; use poem_openapi::OpenApi; #[derive(Clone)] pub struct MyApi { pub handle: SharedHandle, // 保留你的SharedHandle定义 } #[OpenApi] impl MyApi { #[oai(path = "/*full_path", method = "get")] async fn get_resource( &self, Path(full_path): Path<String>, ) -> Result<Json<ResourceResponse>, BadRequest> { // 拆分路径段,过滤空字符串(处理连续/的情况) let path_segments: Vec<&str> = full_path.split('/').filter(|s| !s.is_empty()).collect(); // 验证路径至少包含两段(namespace + id) if path_segments.len() < 2 { return Err(BadRequest("Invalid path: requires at least two segments".into())); } // 提取id和namespace let id = path_segments.last().unwrap().to_string(); let namespace = path_segments[0..path_segments.len()-1].join("/"); // 这里可以正常使用self.handle处理业务逻辑 // 比如 let data = self.handle.fetch_data(&namespace, &id).await?; Ok(Json(ResourceResponse { namespace, id })) } } // 示例响应结构体 #[derive(serde::Serialize)] struct ResourceResponse { namespace: String, id: String, }
关键说明
- 通配符捕获:poem的
*通配符会捕获当前位置到URL结尾的所有路径内容,适合处理不确定数量的前置路径段场景。 - 路径拆分逻辑:通过
split('/')拆分后过滤空值,避免处理//这类无效路径;再通过切片操作分离namespace和id。 - SharedHandle保留:由于处理器是
MyApi结构体的方法,通过&self可以直接访问结构体中的SharedHandle,完全兼容原有使用方式。 - 路由优先级:如果你的API还有其他更具体的路由(比如
/static/*),请将当前处理器放在这些路由之后注册,避免拦截其他请求。
内容的提问来源于stack exchange,提问作者navicore
相关产品推荐
相关产品推荐

