1 个不稳定版本
新功能 0.2.0 | 2024年8月23日 |
---|
#20 in #match
10KB
路由匹配
使用宏进行简单直观的http请求路由的实用工具。
快速示例
使用 route_match
,您可以这样路由请求
use route_match::route;
fn handle_request(reqest: Request) -> Response {
route! {
match (&reqest.method().as_str(), &reqest.uri().path()) {
GET /foo/bar => handle_foo_bar(),
POST /user/:id => handle_post_user(request, id),
_ => handle_404_error(request),
}
}
}
目标
HTTP 路由应该很简单。HTTP 协议在 1996 年达到 1.0 版本 - 它是一种非常成熟的技术,基于 URL 和 HTTP 方法进行路由,并从 URL 路径中提取变量,这个问题现在应该已经得到了很好的解决。
在我的经验中,现有的路由解决方案经常遇到一些陷阱,使得这个过程比本来应该要复杂。
-
它们通常过于 紧密耦合到单一解决方案。一个库可能有很好的路由解决方案,但如果你想使用它,就必须采用它们选择的网络堆栈的其他组件。如果你想要将你的 API 移动到不同的环境中,比如云函数,那里的请求和响应类型受到限制,这并不总是容易。
-
它们通常是“魔法般”的,由于大量使用特质,可能很难 理解,可能会给出令人困惑的错误信息,并且可能需要花费时间来学习使它们工作的“魔法词汇”。
-
它们通常 带有局限性。当你需要将解决方案压缩通过路由接口时,你可能会遇到处理生命周期或异步的问题,这些问题可能没有被库作者预料到或围绕这些问题设计。
-
它们通常 带有运行时成本。路由对象通常会在堆上表示为一个对象,这需要迭代。诚然,这是一个非常非常小的问题,但不必是这样的。
因此,route_match
旨在解决这些问题,并为 Rust 中的 HTTP 请求路由提供一个 简单易用、直观、环境无关 的解决方案。
本项目的优先级是
-
通过过程宏提供易于使用、直观的 DSL 以路由 HTTP 请求
-
让你以 HTTP 协议而非 Rust 语法来思考你的端点
-
在您拥有 HTTP 方法和 URL 路径的任何环境中工作,而不管您使用的其他工具或堆栈如何
-
专注于单一用例,并做好它。这个库并不试图解决所有可能的路由场景,它旨在处理最常见的场景,同时保持精简、最小化、快速下载和快速构建。
使用方法
以下是一个简单的匹配语句示例
fn match_route(method: &str, path: &str) -> boolean {
route! {
match (method, path) {
GET /foo => true,
_ => false,
}
}
}
match_route("GET", "/foo") // returns true
match_route("GET", "foo") // also true - the leading '/' is optional
match_route("POST", "/foo") // returns false - the method must match
match_route("GET", "/bar") // returns false - the path must match
match_route("GET", "/foo/bar") // returns false - the uri path must match completely
提供的方法和路径将按顺序进行检查,并执行第一个匹配的分支。例如,对于如下匹配表达式
fn match_route(method: &str, path: &str) {
route! {
match (method, path) {
_ /foo -> println!("ANY /foo"),
GET /foo => println!("GET /foo"),
_ => println!("default"),
}
}
}
match_route("GET", "/foo") // prints "ANY /foo"
条件 GET /foo
将永远不会被执行,因为 _ /foo
也匹配了 GET
条件。
注意,默认的 _
分支必须始终提供。
URL 路径参数
我们还可以通过在路径模式中插入模式 :var_name
来提取 URL 参数。
fn match_route(method: &str, path: &str) -> boolean {
route! {
match (method, path) {
GET /user/:id => println!("user id: {}", id),
_ => println!("default"),
}
}
}
match_route("GET /user/456") // prints: "GET /user/456"
在这里,id
参数作为 &str
传递给分支表达式。参数的生存期与传递给匹配表达式的 path
参数的生存期相同。
通配符匹配
有时我们想忽略模式的一部分,并 inclusively 匹配
fn match_route(method: &str, path: &str) -> boolean {
route! {
match (method, path) {
// Match any method, so long as the path matches "/foo"
_ /foo => println!("Any /foo"),
// Match any request with the method "OPTIONS"
OPTIONS _ => println!("OPTIONS"),
// Mathc any path starting with "/foo/bar"
// Here "rest" will be bound as an &str containing everything
// in the path following "/foo/bar"
GET /foo/bar/*:rest => println("rest: {}", rest),
// Match any method/path combination at all
_ => println!("default"),
}
}
}
语法
route
宏提供了一个匹配表达式,允许您匹配 HTTP 方法和解析模式。
匹配语句的形式为
match_stmnt :
match
(
,
)
{
}
方法: 表达式 路径: 表达式
在这里,method
和 path
参数可以是任何具有类型 &str
的表达式。
branches
扩展为以下内容
branches : , ? | ? 分支:=> 表达式
pattern : | _ 方法:
GET
|HEAD
|POST
|PUT
|DELETE
|CONNECT
|OPTIONS
|TRACE
|PATCH
|_
uri:<uri_components> |"
<uri_components>"
|_
uri_components :
/
<uri_component> <uri_components>? |/
<uri_component>? uri_component:标识符 |:
标识符
运行时规范
在运行时,匹配语句执行第一个分支表达式,以便提供的方法和路径与分支模式匹配。
依赖项
~270–720KB
~17K SLoC