You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 13:07:34