3个版本 (1个稳定版)

1.0.0 2024年6月28日
0.2.0 2024年3月7日
0.1.0 2024年2月29日

#213 in 配置

Download history 17/week @ 2024-05-20 12/week @ 2024-05-27 18/week @ 2024-06-03 12/week @ 2024-06-10 5/week @ 2024-06-17 142/week @ 2024-06-24 37/week @ 2024-07-01 4/week @ 2024-07-08 15/week @ 2024-07-15 36/week @ 2024-07-22 16/week @ 2024-07-29

每月 71次下载
用于 6 crate

MIT 许可证

76KB
1.5K SLoC

点击这里查看中文文档

几乎所有应用程序都提供交互式界面。由于不同协议的存在,不同类型的接口没有统一的路由规则,这可能导致程序结构混乱,难以统一方便地控制各种接口。为了解决这个问题,DCE提供了一个标准的路由器,并封装了可路由协议的特性。对于没有标准URI路径的接口,只要它们实现了可路由协议特性,就可以通过DCE路由器进行统一路由。

DCE-RUST不仅封装了主要路由器,还包括会话管理器。与路由器一起,它实现了平滑的权限控制。除了基本会话存储接口外,会话管理器还实现了用户会话、长连接会话和自生成会话管理器,便于用户级会话的管理。有关更详细的文档,请点击这里

DCE路由器包位于crates/router,可路由协议实现的示例位于crates/protocols。DCE路由器的应用程序示例代码位于src目录下。目录结构解释如下

[ROOT]
├──assets                               Resource directory
│  ├──templates                         HTML and other template directory
├──crates                               Crate directory
│  ├──macro                             DCE macro package
│  ├──protocols                         Routable protocol implementation package directory
│  │  ├──cli                            CLI routable protocol implementation
│  │  ├──hyper                          Hyper HTTP routable protocol implementation
│  │  ├──tokio                          Tokio TCP/UDP routable protocol implementation (this implementation is example code and not recommended for direct use in real projects)
│  │  ├──tokio-tungstenite              Tokio Tungstenite WebSocket routable protocol implementation (this implementation is example code and not recommended for direct use in real projects)
│  ├──router                            DCE router package
│  ├──session                           DCE session management package
│  ├──util                              DCE util package
├──src                                  DCE application example code
│  ├──apis                              Route interface example code

关于可路由协议特性,由于HTTP和CLI有标准的路径地址用于路由,这些实现通常适用于实际项目。对于其他实现,如TCP可路由协议,它们目前主要用作示例代码,因为像TCP这样的通信协议通常在顶部定义一个新的业务协议,并且没有统一的标准。因此,用户需要实现相应的可路由协议以适应DCE路由器。

除了基本路由功能外,DCE路由器还提供全局控制器预事件/后事件接口,并且请求对象提供数据转换和序列化实用接口。

  • 全局控制器预事件接口可以执行一些预处理工作,例如全局权限控制,在这里操作非常方便。
  • 数据转换器,用于在 DTOENTITY 之间进行转换。通过自己实现 From/Into 特性,可以对实体数据进行脱敏等操作,将其转换为适合传输的数据结构。
  • 用于将 DTO 序列化以进行传输或将 sequences 解析为 DTO 以转换为实体对象的序列化接口。具体的序列化工具通过 api 宏进行配置。

路由性能

由于处理链非常短,它直接在通过路径匹配API后调用控制器,因此性能非常高。对于常规路径API,它直接从API哈希表中匹配路径,时间复杂度为O(1)。对于变量路径API,如果路径中只有一个变量,时间复杂度为O(n),如果有多个变量,则呈指数增长。因此,建议使用常规路径,或者确保变量路径中的变量数量尽可能少,或者确保同变量尽可能少,以实现最高的路由性能。

完整的路由流程图

Router flow

DCE路由器使用示例

对于更完整的示例,请参阅 src 目录,对于更详细的文档,请点击 此处

use rand::random;
use serde::Serialize;
use dce_cli::protocol::{CliProtocol, Cli, CliGet};
use dce_macro::{api, openly_err};
use dce_router::router::Router;
use dce_router::serializer::JsonSerializer;

#[tokio::main]
async fn main() {
    let router = Router::new().unwrap()
        .push(hello)
        .push(session)
        .ready().unwrap();

    CliProtocol::new(1).route(router.clone(), Default::default()).await;
}

/// `cargo run --package dce --bin app -- hello`
/// `cargo run --package dce --bin app -- hello DCE`
#[api("hello/{target?}")]
pub async fn hello(req: Cli) {
    let target = req.param("target")?.get().unwrap_or("RUST").to_owned();
    req.raw_resp(format!("Hello {} !", target))
}

/// `cargo run --package dce --bin app -- manager`
/// `cargo run --package dce --bin app -- manager --user DCE`
#[api(serializer = JsonSerializer{})]
pub async fn session(mut req: CliGet<UserDto>) {
    let name = req.rp_mut().args_mut().remove("--user").ok_or_else(|| openly_err!(r#"please pass in the "--user" arg"#))?;
    let resp = User {
        nickname: name.clone(),
        gender: if random::<u8>() > 127 { Gender::Female } else { Gender::Male },
        name,
        cellphone: "+8613344445555".to_owned(),
    };
    req.resp(resp)
}

#[derive(Serialize)]
pub enum Gender {
    Male,
    Female,
}

pub struct User {
    nickname: String,
    gender: Gender,
    #[allow(dead_code)]
    name: String,
    #[allow(dead_code)]
    cellphone: String,
}

#[derive(Serialize)]
pub struct UserDto {
    nickname: String,
    gender: Gender,
}

impl From<User> for UserDto {
    fn from(value: User) -> Self {
        Self {
            nickname: value.nickname,
            gender: value.gender,
        }
    }
}

依赖项

~1–1.9MB
~40K SLoC