2.深入剖析 Rust+Axum 类型安全路由系统
摘要
详细解读 Rust+Axum 路由系统的关键设计原理,涵盖基于 Rust 类型系统的路由匹配机制、动态路径参数与正则表达式验证以及嵌套路由与模块化组织等多种特性。
一、引言
在现代 Web 开发中,路由系统是构建 Web 应用的核心组件之一,它负责将客户端的请求映射到相应的处理函数。Rust 作为一门系统级编程语言,以其内存安全、高性能和并发处理能力而闻名。Axum 是一个基于 Rust 的轻量级 Web 框架,它提供了一个类型安全的路由系统,能够在编译时捕获许多常见的错误,提高代码的可靠性和可维护性。本文将深入探讨 Rust+Axum 类型安全路由系统的设计原理,包括路由匹配机制、动态路径参数与正则表达式验证以及嵌套路由与模块化组织。
二、基于 Rust 类型系统的路由匹配机制
2.1 静态路由匹配
Axum 的路由系统首先支持静态路由匹配。静态路由是指 URL 路径完全固定的路由,例如 /hello。在 Axum 中,我们可以使用 route 方法来定义静态路由。以下是一个简单的示例:
use axum::{routing::get,Router,
};
use std::net::SocketAddr;// 处理函数
async fn hello() -> &'static str {"Hello, World!"
}#[tokio::main]
async fn main() {// 构建路由let app = Router::new().route("/hello", get(hello));// 监听地址let addr = SocketAddr::from(([127, 0, 0, 1], 3000));// 启动服务器axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}
在这个示例中,我们定义了一个静态路由 /hello,当客户端访问该路径时,服务器将调用 hello 处理函数并返回 "Hello, World!"。Axum 在编译时会检查路由路径和处理函数的类型是否匹配,确保只有正确的请求才能到达相应的处理函数。
2.2 动态路由匹配
除了静态路由,Axum 还支持动态路由匹配。动态路由允许在 URL 路径中包含参数,这些参数可以在处理函数中提取和使用。例如,我们可以定义一个动态路由 /users/:id,其中 :id 是一个参数。在 Axum 中,我们可以使用 Path 提取器来提取动态路径参数。以下是一个示例:
use axum::{routing::get,Router,extract::Path,
};
use std::net::SocketAddr;// 处理函数
async fn get_user(Path(id): Path<String>) -> String {format!("Getting user with ID: {}", id)
}#[tokio::main]
async fn main() {// 构建路由let app = Router::new().route("/users/:id", get(get_user));// 监听地址let addr = SocketAddr::from(([127, 0, 0, 1], 3000));// 启动服务器axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}
在这个示例中,当客户端访问 /users/123 时,Axum 会将 123 作为参数提取出来,并传递给 get_user 处理函数。通过 Rust 的类型系统,Axum 确保了参数的类型和处理函数的参数类型一致,从而实现了类型安全的动态路由匹配。
三、动态路径参数与正则表达式验证
3.1 Path<String> 提取器
Path<String> 提取器是 Axum 中用于提取动态路径参数的常用工具。它可以将路径中的参数提取为 String 类型。例如,在上面的 /users/:id 路由中,我们使用 Path<String> 提取器将 id 参数提取出来。这种方式非常灵活,但有时我们可能需要对参数进行更严格的验证。
3.2 正则表达式验证
Axum 可以结合正则表达式对动态路径参数进行验证。虽然 Axum 本身没有直接提供正则表达式验证的功能,但我们可以通过自定义提取器来实现。以下是一个简单的示例,用于验证 id 参数是否为数字:
use axum::{routing::get,Router,extract::{Path, rejection::ExtractRejection},http::Request,body::Body,response::IntoResponse,
};
use std::net::SocketAddr;
use regex::Regex;// 自定义提取器
struct ValidId(u32);impl axum::extract::FromRequest<Body> for ValidId {type Rejection = ExtractRejection;async fn from_request(req: &mut Request<Body>) -> Result<Self, Self::Rejection> {let path = req.uri().path();let re = Regex::new(r"/users/(\d+)").unwrap();if let Some(captures) = re.captures(path) {if let Ok(id) = captures[1].parse::<u32>() {return Ok(ValidId(id));}}Err(ExtractRejection::default())}
}// 处理函数
async fn get_user(ValidId(id): ValidId) -> String {format!("Getting user with ID: {}", id)
}#[tokio::main]
async fn main() {// 构建路由let app = Router::new().route("/users/:id", get(get_user));// 监听地址let addr = SocketAddr::from(([127, 0, 0, 1], 3000));// 启动服务器axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}
在这个示例中,我们自定义了一个 ValidId 提取器,使用正则表达式验证 id 参数是否为数字。如果验证通过,将参数转换为 u32 类型并传递给处理函数;否则,返回一个拒绝响应。
四、嵌套路由与模块化组织
4.1 嵌套路由
Axum 支持嵌套路由,这使得我们可以将路由组织成更复杂的结构。例如,我们可以将所有与用户相关的路由放在一个子路由中,将所有与文章相关的路由放在另一个子路由中。以下是一个示例:
use axum::{routing::get,Router,
};
use std::net::SocketAddr;// 用户路由处理函数
async fn get_users() -> &'static str {"Getting all users"
}async fn get_user() -> &'static str {"Getting a single user"
}// 文章路由处理函数
async fn get_articles() -> &'static str {"Getting all articles"
}async fn get_article() -> &'static str {"Getting a single article"
}#[tokio::main]
async fn main() {// 构建用户子路由let user_routes = Router::new().route("/", get(get_users)).route("/:id", get(get_user));// 构建文章子路由let article_routes = Router::new().route("/", get(get_articles)).route("/:id", get(get_article));// 构建主路由let app = Router::new().nest("/users", user_routes).nest("/articles", article_routes);// 监听地址let addr = SocketAddr::from(([127, 0, 0, 1], 3000));// 启动服务器axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}
在这个示例中,我们将用户路由和文章路由分别组织成子路由,然后将它们嵌套到主路由中。这样可以使代码更加模块化,易于维护和扩展。
4.2 模块化组织
除了嵌套路由,我们还可以将路由逻辑模块化。例如,我们可以将用户路由的处理函数和路由定义放在一个模块中,将文章路由的处理函数和路由定义放在另一个模块中。以下是一个示例:
use axum::{routing::get,Router,
};
use std::net::SocketAddr;// 用户路由模块
mod user_routes {use super::*;// 用户路由处理函数pub async fn get_users() -> &'static str {"Getting all users"}pub async fn get_user() -> &'static str {"Getting a single user"}// 构建用户路由pub fn router() -> Router {Router::new().route("/", get(get_users)).route("/:id", get(get_user))}
}// 文章路由模块
mod article_routes {use super::*;// 文章路由处理函数pub async fn get_articles() -> &'static str {"Getting all articles"}pub async fn get_article() -> &'static str {"Getting a single article"}// 构建文章路由pub fn router() -> Router {Router::new().route("/", get(get_articles)).route("/:id", get(get_article))}
}#[tokio::main]
async fn main() {// 构建主路由let app = Router::new().nest("/users", user_routes::router()).nest("/articles", article_routes::router());// 监听地址let addr = SocketAddr::from(([127, 0, 0, 1], 3000));// 启动服务器axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}
在这个示例中,我们将用户路由和文章路由分别封装在不同的模块中,每个模块都有自己的处理函数和路由定义。这样可以使代码更加清晰,易于管理和复用。
五、总结
Rust+Axum 类型安全路由系统通过利用 Rust 的类型系统,实现了静态路由和动态路由的类型安全匹配。同时,结合正则表达式验证和嵌套路由、模块化组织等特性,使得路由系统更加灵活、可维护和易于扩展。在实际开发中,合理运用这些特性可以提高代码的质量和开发效率,为构建高性能、可靠的 Web 应用提供有力支持。
相关文章:
2.深入剖析 Rust+Axum 类型安全路由系统
摘要 详细解读 RustAxum 路由系统的关键设计原理,涵盖基于 Rust 类型系统的路由匹配机制、动态路径参数与正则表达式验证以及嵌套路由与模块化组织等多种特性。 一、引言 在现代 Web 开发中,路由系统是构建 Web 应用的核心组件之一,它负责…...
c# 委托和事件的区别及联系,Action<T1,T2>与Func<T1,T2>的区别
定义与本质 委托: 委托是一种类型,用于存储对方法的引用。它允许将方法作为参数传递、存储和调用。委托可以绑定一个或多个方法,并通过和-操作符动态添加或移除方法。 事件: 事件是基于委托的封装,提供了一种发布/订阅机制。事件…...
【Python入门】文件读取全攻略:5种常用格式(csv/excel/word/ppt/pdf)一键搞定 | 附完整代码示例
大家好,我是唐叔!今天给大家带来一篇Python文件读取的终极指南。无论是数据分析、办公自动化还是爬虫开发,文件读取都是Python程序员必须掌握的核心技能。本文将详细介绍Python处理5大常用文件格式的方法,包含完整可运行的代码示例…...
【Git】git的简单使用
文章目录 1. 基础概念2. 简单使用2.1 git配置2.1.1 git的配置文件2.1.2 .gitignore文件 2.2 创建仓库2.2.1 创建本地仓库2.2.2 github创建远程仓库step1:github新建一个代码仓step2:创建密钥远程仓库相关指令2.2.3 本地仓库 关联 远程仓库 2.3 分支2.3.1…...
WebSocket 实现数据实时推送原理
WebSocket 实现数据实时推送的核心机制在于其全双工通信能力和持久的连接特性。以下是其工作原理的详细步骤: 1. 握手阶段(HTTP 升级协议) 客户端发起请求:通过发送一个带有特殊头部的 HTTP 请求,请求协议升级。 GET …...
LeetCode 2919 使数组变美的最小增量运算数
动态规划解题:最小操作次数使数组变为美丽数组 问题描述 给定一个下标从0开始、长度为n的整数数组nums和一个整数k。你可以对数组中的任意一个元素进行加1操作,操作次数不限。如果数组中任意长度大于或等于3的子数组的最大值都大于或等于k,…...
[Web 安全] Web 信息收集 —— 信息收集流程
🌟 想系统化学习 Web 渗透?看看这个:[Web 安全] Web 安全攻防 学习手册 提示:本章不涉及任何具体信息收集技术,仅仅是讲解收集这些信息我能干啥,以及如何才能比较全面的收集信息。 0x01:信息收…...
内部聊天软件,BeeWorks-安全的企业内部通讯软件
企业在享受数据便利的同时,如何保障企业数据安全已经成为无法回避的重要课题。BeeWorks作为一款专为企业设计的内部通讯软件,通过全链路的安全能力升维,为企业提供了一个安全、高效、便捷的沟通协作平台,全面保障企业数据安全。 …...
线程安全学习
1 什么是线程 线程是cpu调度的最小单位,在Linux 下 实现线程的方式为轻量级进程,复用进程的结构体,使用clone函数创建 2 线程安全 所谓线程安全,更确切的应该描述为内存安全 #include <stdio.h> #include <pthread.h…...
应用篇02-镜头标定(上)
本节主要介绍相机的标定方法,包括其内、外参数的求解,以及如何使用HALCON标定助手实现标定。 计算机视觉——相机标定(Camera Calibration)_摄像机标定-CSDN博客 1. 原理 本节介绍与相机标定相关的理论知识,不一定全,可以参考相…...
【UE5 C++】“ProceduralMeshComponent”的使用记录
效果 如下所示,通过“ProceduralMeshComponent”创建了一个自定义形状的Mesh,并且该Mesh包含碰撞信息,然后2s后更新Mesh形状。 步骤 1. 在“xxx.Build.cs”中引入“ProceduralMeshComponent”模块 2. 新建一个Actor类,这里命名为…...
解决PIP 安装出错ERROR: cp310-cp310-manylinux_2_28_x86_64.whl is not a supported wheel
ERROR: torch-2.8.0.dev20250325cu128-cp310-cp310-manylinux_2_28_x86_64.whl is not a supported wheel on this platform. 可以 pip debug --verbose | grep manylinux | grep cp310 WARNING: This command is only meant for debugging. Do not use this with automation f…...
通过helm在k8s中安装mysql 8.0.37
使用 Helm 在 Kubernetes 中安装 MySQL 8.0.37 是一个相对简单的过程。以下是详细步骤: 下载helm包 #添加 Helm 仓库 helm repo add bitnami https://charts.bitnami.com/bitnami#搜索mysql helm search repo mysql --versions NAME CHAR…...
【暴力求解】1534. 统计好三元组
1534. 统计好三元组 - 力扣(LeetCode) 给你一个整数数组 arr ,以及 a、b 、c 三个整数。请你统计其中好三元组的数量。 如果三元组 (arr[i], arr[j], arr[k]) 满足下列全部条件,则认为它是一个 好三元组 。 0 < i < j &l…...
前端页面效果收集
文章目录 数字雨元素融化动画电子签名共享屏幕 数字雨 <canvas id"matrix"></canvas> <script>const canvas document.getElementById(matrix);const ctx canvas.getContext(2d);canvas.width window.innerWidth;canvas.height window.innerH…...
(leetcode算法题)309. 买卖股票的最佳时机含冷冻期
按照题目要求,研究对象是最后一天结束后获得的最大利润 那么就可以把问题拆分成 第 1 天结束后获得的最大利润, 第 2 天结束后获得的最大利润, 第 i 天结束后获得的最大利润, 由于规则中强调不能同时参与多笔交易,…...
Chrome漏洞可窃取数据并获得未经授权的访问权限
在发现两个关键漏洞后,谷歌发布了Chrome浏览器的紧急安全更新。这些漏洞可能允许攻击者窃取敏感数据并未经授权访问用户系统。 这些缺陷被识别为CVE-2025-3619和CVE-2025-3620,在Windows和Mac的135.0.7049.95/.96之前影响Chrome版本,影响Linux的135.0.7049.95/.96。该更新将在…...
.net core 项目快速接入Coze智能体-开箱即用-全局说明
目录 一、Coze智能体的核心价值 二、开箱即用-效果如下 三 流程与交互设计 为什么要分析意图,而不是全部交由AI处理。 四 接入前的准备工作 五:代码实现----字节Coze 签署 JWT和获取Token .net core 项目快速接入Coze智能体-开箱即用 .net core快…...
风丘年度活动:2025年横滨汽车工程展览会
| 展会简介: 2025年横滨汽车工程展览会,是由日本汽车工程师学会(JSAE)精心主办的一场行业盛会。预计届时将汇聚超550家参展商,设置1300个展位,展览面积超过20000平方米。展会受众广泛,面向汽车…...
Redis线上操作最佳实践有哪些?
大家好,我是锋哥。今天分享关于【Redis线上操作最佳实践有哪些?】面试题。希望对大家有帮助; Redis线上操作最佳实践有哪些? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在使用 Redis 时,尤其是在生产环境中,合理…...
Gin趣讲
故事背景:Gin快递公司 假设你开了一家名叫“Gin快递”的公司,专门帮客户寄包裹。客户会通过电话(也就是HTTP请求)告诉你他们要寄什么东西,你的公司得快速接单、分任务、处理包裹,最后把结果送回去。Gin框架…...
Redis——五种数据类型
目录 前言 1.String 1.1RAW编码 1.2EMBSTR编码 1.3 INT编码 2.List 3.Set 3.1 InSet编码转化成Dict编码 4.ZSet 4.1结合SkipList和HT实现 4.2使用ZipList实现 4.3编码转换 4.4 ZipList排序功能 5.Hash 5.1Hash底层存储结构 6.Redis数据结构和数据类型关系图 前言…...
Godot学习-创建简单动画
文章目录 1、准备工作Godot资源 2、创建项目3、创建结点4、创建动画1、创建动画2、添加轨道3、创建关键帧3.1 第一个关键帧3.2 第二个关键帧 5、加载后自动播放6、动画循环7、轨道设置1、轨道更新模式2、轨迹插值3、其他属性的关键帧4、编辑关键帧5、使用 RESET 轨道6、洋葱皮 …...
论文阅读VACE: All-in-One Video Creation and Editing
code:https://github.com/ali-vilab/VACE 核心 单个模型同时处理多种视频生成和视频编辑任务通过VCU(视频条件单元)进行实现 方法 视频任务 所有的视频相关任务可以分为4类 文本生视频 参考图片生视频 视频生视频 视频mask生视频 VCU …...
JavaSE学习(前端初体验)
文章目录 前言一、准备环境二、创建站点(创建一个文件夹)三、将站点部署到编写器中四、VScode实用小设置五、案例展示 前言 首先了解前端三件套:HTML、CSS、JS HTML:超文本标记语言、框架层、描述数据的; CSS…...
AlmaLinux 9.2 安装 snmp 后 sshd 服务无法启动
问题 AlmaLinux 9.2 安装 net-snmp 后导致 sshd 无法启动,SSH 无法正常连接。并且在日志中发现OpenSSL version mismatch. Built against 30000010, you have 30200020错误。 问题排查 AlmaLinux 9.2 初始安装 openssl 的版本为 3.0.7。软件包为openssl-3.0.7-6。…...
前端渲染pdf文件解决方案
一、前言 在当今数字化信息传播的时代,PDF文档作为一种常见的文件格式扮演着重要的角色。对于前端开发者而言,实现在网页上渲染和展示PDF文件是一项常见但也具有挑战性的任务。幸运的是,现在有一个强大的工具——react-pdf-viewer,…...
Kubernetes(K8S)内部功能总结
Kubernetes(K8S)是云技术的最核心的部分,也是构建是云原生的基石 K8S K8S,是Kubernetes的缩写,是Google开发的容器编排平台,现在由云原生计算基金会(CNCF)进行维护。 K8Sÿ…...
蓝桥杯日期的题型
做题思路 一般分为3个步骤,首先要定义一个结构体来存储月份的天数,第一循环日期,第二判断日期是否为闰年,第三就是题目求什么 结构体 static int[] ds{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 判断是否闰年的函数 public static void f(int m,int d){//被4整…...
【计算机网络】3数据链路层①
这篇笔记专门讲数据链路层的功能。 2.功能 数据链路层的主要任务是让帧在一段链路上或一个网络中传输。 2.1.封装成帧(组帧) 解决的问题:①帧定界②帧同步③透明传输 实现组帧的方法通常有以下种。 2.1.1.字符计数法 原理:在每个帧开头,用一个定长计数字段来记录该…...
