如何处理Axum Rust中API Gateway到Lambda的带Stage路由URL?
处理API Gateway Stage前缀对Axum路由的影响
给你几个可行的解决思路:
1. 在API Gateway端去掉Stage前缀
直接通过自定义域名配置把Stage映射到根路径:
- 申请并绑定API Gateway的自定义域名,然后创建基础路径映射,把目标Stage(比如
testStage)和自定义域名的空路径(/)关联起来。这样用户请求自定义域名时,URL里就不会带testStage前缀了。 - 如果用Terraform、CloudFormation这类IaaC工具,直接配置对应的
base_path_mapping资源就行,把base_path设为空字符串,指向目标Stage。
2. 在Axum里动态剥离Stage前缀
写个自定义中间件,从API Gateway的请求事件里拿到stage字段,然后修改请求URI去掉这个前缀,再交给路由匹配:
use aws_lambda_events::apigw::ApiGatewayProxyRequest; use axum::{http::Uri, middleware::Next, response::IntoResponse, Request}; async fn strip_stage_prefix<B>(mut req: Request<B>, next: Next<B>) -> impl IntoResponse { // 从请求扩展中取出API Gateway的原始事件(需要提前把事件注入扩展) if let Some(event) = req.extensions().get::<ApiGatewayProxyRequest>() { let stage = &event.request_context.stage; let uri_str = req.uri().to_string(); // 替换掉URI里的stage前缀 if let Ok(new_uri) = uri_str.replace(&format!("/{}", stage), "").parse::<Uri>() { *req.uri_mut() = new_uri; } } next.run(req).await }
然后把这个中间件挂载到路由上:
let app = Router::new() .route("/messages/message/:id", get(get_message)) .layer(axum::middleware::from_fn(strip_stage_prefix));
注意:需要在Lambda处理函数里,把ApiGatewayProxyRequest实例注入到Axum请求的扩展中,这样中间件才能拿到stage信息。
3. 用环境变量动态配置Axum路由前缀
通过IaaC部署时,给Lambda设置一个STAGE环境变量,值就是当前部署的stage名称,然后在Axum里动态生成带前缀的路由:
use std::env; use axum::Router; // 读取环境变量,默认用prod let stage = env::var("STAGE").unwrap_or_else(|_| "prod".to_string()); let app = Router::new() .nest(&format!("/{}", stage), Router::new() .route("/messages/message/:id", get(get_message)) );
这样不管部署到哪个stage,路由都会自动匹配对应的前缀,不用手动改代码。
内容的提问来源于stack exchange,提问作者Lacrosse343
相关产品推荐
相关产品推荐

