如何在Warp服务器中用Tower中间件实现基于IP的请求拦截
整合Warp路由、Tower中间件与localhost IP过滤
核心思路是把IP过滤实现为Warp过滤器,而非在make_service_fn层面处理,这样就能和现有路由、Tower中间件无缝组合——因为Warp的路由系统本身就是基于过滤器链设计的。
步骤1:实现localhost专属过滤器
编写一个过滤器,校验请求的远程IP是否为回环地址(127.0.0.1或::1),不符合则返回拒绝:
use warp::Filter; use std::net::IpAddr; // 校验请求来源是否为localhost的过滤器 fn localhost_only() -> impl Filter<Extract = (), Error = warp::Rejection> + Clone { warp::addr::remote() .and_then(|addr: Option<IpAddr>| async move { match addr { // 匹配IPv4/IPv6回环地址 Some(IpAddr::V4(v4)) if v4.is_loopback() => Ok(()), Some(IpAddr::V6(v6)) if v6.is_loopback() => Ok(()), // 非localhost来源,返回自定义拒绝 _ => Err(warp::reject::custom(LocalhostOnly)), } }) } // 自定义拒绝类型,用于区分IP校验失败的场景 #[derive(Debug)] struct LocalhostOnly; impl warp::reject::Reject for LocalhostOnly {}
步骤2:处理拒绝响应
为自定义的LocalhostOnly拒绝添加错误处理逻辑,返回标准的403 Forbidden:
// 统一处理路由拒绝,针对IP校验失败返回403 async fn handle_rejection(err: warp::Rejection) -> Result<impl warp::Reply, warp::Rejection> { if err.find::<LocalhostOnly>().is_some() { Ok(warp::http::StatusCode::FORBIDDEN) } else { // 其他拒绝场景交给Warp默认处理 Err(err) } }
步骤3:整合路由、Tower中间件与IP过滤
将IP过滤器绑定到需要保护的特定端点,同时通过Warp的with()方法直接应用Tower中间件(限流、超时):
use tower::limit::ConcurrencyLimitLayer; use tower::timeout::TimeoutLayer; use std::time::Duration; use tokio; #[tokio::main] async fn main() { // 受保护的/admin端点:仅localhost可访问,叠加限流+超时中间件 let admin_route = warp::path("admin") .and(localhost_only()) // 绑定IP过滤规则 .and(warp::get()) .map(|| "Admin access granted (localhost only)") // 应用Tower限流中间件:最多允许5个并发请求 .with(warp::filters::service::layer(ConcurrencyLimitLayer::new(5))) // 应用Tower超时中间件:请求超过10秒则终止 .with(warp::filters::service::layer(TimeoutLayer::new(Duration::from_secs(10)))); // 公开的/public端点:无IP限制,可按需添加中间件 let public_route = warp::path("public") .and(warp::get()) .map(|| "Public access granted"); // 组合所有路由,并挂载拒绝处理逻辑 let routes = admin_route.or(public_route).recover(handle_rejection); // 启动Warp服务器 warp::serve(routes).run(([127, 0, 0, 1], 3030)).await; }
关键优势
- 无需修改
make_service_fn,完全复用Warp的路由组合能力 - IP过滤仅作用于指定端点,不影响其他公开路由
- Tower中间件通过
warp::filters::service::layer()直接整合,和原有中间件逻辑兼容 - 路由结构清晰,易于扩展其他过滤规则或中间件
内容的提问来源于stack exchange,提问作者Aditeya
相关产品推荐
相关产品推荐

