路由
2025/4/6大约 3 分钟hyperlanewebrustusage-introductionroute
静态路由
提示
hyperlane 框架支持静态路由(如果重复注册相同的静态路由,框架会抛出异常,程序退出运行),使用方法如下:
原生写法
struct Route;
impl ServerHook for Route {
async fn new(_: &mut Stream, _: &mut Context) -> Self {
Self
}
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
Status::Continue
}
}
let mut server: Server = Server::default();
server.route::<Route>("/test");属性宏写法
use hyperlane::*;
use hyperlane_macros::*;
#[route("/test")]
struct Route;
impl ServerHook for Route {
async fn new(_: &mut Stream, _: &mut Context) -> Self {
Self
}
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
Status::Continue
}
}动态路由
提示
hyperlane 框架支持动态路由(如果重复注册相同模式的动态路由,框架会抛出异常,程序退出运行),具体使用方法如下:
注册
提示
动态路由使用 {} 包裹,有两种写法
{key}内直接写字符串,则将匹配的value存入key对应的value中。{key:regex}则将正则表达式匹配的value存入key对应的value中,如果路径的最后是正则动态路由,则匹配后续所有路径,例如/test/{file:^.*$}匹配/test/a/b/c/d会成功,file的value为a/b/c/d。如果路径的最后不是正则动态路由,则仅使用正则匹配当前段的路由,例如/test/{file:^.*$}/b匹配/test/a/b会成功,file的value为a。
朴素动态路由
原生写法
server.route::<Route>("/test/{text}");属性宏写法
#[route("/test/{text}")]
struct Route;正则表达式动态路由
原生写法
server.route::<Route>("/test/{number:\\d+}");属性宏写法
#[route("/test/{number:\\d+}")]
struct Route;获取全部动态路由参数
ctx.get_route_params();获取某个动态路由参数
// 尝试获取路由参数
let param: Option<String> = ctx.try_get_route_param("text");
// 获取路由参数(获取不到则panic)
let param: String = ctx.get_route_param("text");使用属性宏获取路由参数
提示
可以使用 #[route_param] 或 #[try_get_route_param] 属性宏提取路由参数。
安全获取路由参数(返回 Option)
use hyperlane::*;
use hyperlane_macros::*;
#[route("/route_param/:test")]
struct RouteParam;
impl ServerHook for RouteParam {
async fn new(_: &mut Stream, _: &mut Context) -> Self {
Self
}
#[response_body(&format!("route param: {request_route_param:?}"))]
#[try_get_route_param("test" => request_route_param)]
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
Status::Continue
}
}不安全获取路由参数(获取失败会 Panic)
#[route_param("test" => request_route_param)]
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
Status::Continue
}获取全部路由参数
#[route_params(request_route_params)]
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
// request_route_params is available as RouteParams
Status::Continue
}获取路由匹配器
let route_matcher: &RouteMatcher = server.get_route_matcher();获取所有路由的信息
let route_matcher: &RouteMatcher = server.get_route_matcher();
for key in route_matcher.get_static_route().keys() {
println!("Static route: {key}");
}
for value in route_matcher.get_dynamic_route().values() {
for (route_pattern, _) in value {
println!("Dynamic route: {route_pattern}");
}
}
for value in route_matcher.get_regex_route().values() {
for (route_pattern, _) in value {
println!("Regex route: {route_pattern}");
}
}路由过滤属性宏
提示
hyperlane 框架提供了多种路由过滤属性宏,可以根据请求的 Host、Referer 等信息过滤请求。 当过滤条件不满足时,直接返回 Status::Continue,跳过当前路由。
Host 过滤
提示
只有当请求的 Host 头匹配指定值时,才会执行 handle 方法。
#[host("example.com")]
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
// Only requests with Host: example.com will reach here
Status::Continue
}Host 拒绝
提示
当请求的 Host 头匹配指定值时,返回 Status::Reject,拒绝请求。
#[reject_host("blocked.com")]
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
// Requests with Host: blocked.com will be rejected
Status::Continue
}Referer 过滤
提示
只有当请求的 Referer 头匹配指定值时,才会执行 handle 方法。
#[referer("https://example.com")]
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
// Only requests with Referer: https://example.com will reach here
Status::Continue
}Referer 拒绝
提示
当请求的 Referer 头匹配指定值时,返回 Status::Reject,拒绝请求。
#[reject_referer("https://malicious.com")]
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
// Requests with Referer: https://malicious.com will be rejected
Status::Continue
}自定义过滤
提示
可以使用 #[filter] 进行自定义条件过滤。当条件不满足时返回 Status::Continue,跳过当前路由。
#[filter(ctx.get_request().get_method() == &RequestMethod::Get)]
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
Status::Continue
}自定义拒绝
提示
可以使用 #[reject] 进行自定义条件拒绝。当条件满足时返回 Status::Reject,拒绝请求。
#[reject(ctx.get_request().get_path().len() > 1000)]
async fn handle(self, stream: &mut Stream, ctx: &mut Context) -> Status {
Status::Continue
}