8 个版本

0.4.1 2023年7月18日
0.4.0 2023年5月5日
0.3.0 2022年11月30日
0.2.2 2022年11月17日
0.1.0 2022年6月28日

#898 in 网页编程

Download history 9/week @ 2024-03-20 73/week @ 2024-03-27 32/week @ 2024-04-03 4/week @ 2024-04-10 5/week @ 2024-04-17 8/week @ 2024-04-24 1/week @ 2024-05-01 2/week @ 2024-05-08 6/week @ 2024-05-15 10/week @ 2024-05-22 12/week @ 2024-05-29 8/week @ 2024-06-05 8/week @ 2024-06-12 10/week @ 2024-06-19 6/week @ 2024-06-26 41/week @ 2024-07-03

67 每月下载次数
4 crates 中使用

Apache-2.0/MIT

175KB
4K SLoC

submillisecond

一个针对 Rust 语言的疯狂网页框架。

Submillisecond 是一个基于 Rust 语言的 后端 网页框架,围绕 WebAssembly 的安全性和 lunatic 调度器

这是一个早期项目,可能存在错误,API 仍在变化。另外,需要注意的是,许多 Rust crate 还不能编译成 WebAssembly,因此不能与 submillisecond 一起使用。

如果您想寻求帮助或只是关注 Lunatic & submillisecond 的讨论,请 加入我们的 Discord 服务器

特性

  • 快速的编译时间
  • 无异步 - 所有抢占和调度都由 lunatic 完成
  • 强大的安全性 - 每个请求都在一个单独的 lunatic 进程中处理
  • 包含电池
    • Cookie
    • Json
    • 日志记录
    • WebSocket
  • Submillisecond LiveView - 前端网页框架

代码示例

use submillisecond::{router, Application};

fn index() -> &'static str {
    "Hello :)"
}

fn main() -> std::io::Result<()> {
    Application::new(router! {
        GET "/" => index
    })
    .serve("0.0.0.0:3000")
}

开始使用 lunatic

要运行示例,您需要先按照 此存储库 中的安装步骤下载 lunatic 运行时。运行时只是一个单独的可执行文件,可在 Windows、macOS 和 Linux 上运行。如果您已经安装了 Rust,可以使用以下命令获取它:

cargo install lunatic-runtime

Lunatic应用程序需要在运行时执行之前编译为WebAssembly。Rust对WebAssembly有很好的支持,你只需将--target=wasm32-wasi标志传递给cargo,就可以构建一个兼容Lunatic的应用程序,例如:

# Add the WebAssembly target
rustup target add wasm32-wasi
# Build the app
cargo build --release --target=wasm32-wasi

这将在你项目的target/wasm32-wasi/release/文件夹中生成一个.wasm文件。现在你可以通过将生成的.wasm文件传递给Lunatic来运行你的应用程序,例如:

lunatic target/wasm32-wasi/release/<name>.wasm

更好的开发者体验

为了简化使用cargo开发和运行Lunatic应用程序,你可以在项目中添加一个.cargo/config.toml文件,内容如下:

[build]
target = "wasm32-wasi"

[target.wasm32-wasi]
runner = "lunatic"

现在你可以使用你熟悉的命令,例如cargo runcargo test,cargo将自动将你的项目构建为WebAssembly模块并在lunatic中运行。

开始使用submillisecond

将其作为依赖项添加

submillisecond = "0.3.0"

处理器

处理器是返回实现IntoResponse响应的函数。

它们可以有任意数量的参数,其中每个参数都是一个提取器

fn index(body: Vec<u8>, cookies: Cookies) -> String {
    // ...
}

路由器

Submillisecond提供了一个router!宏来定义应用中的路由。

#[derive(NamedParam)]
struct User {
    first_name: String,
    last_name: String,
}

fn hi(user: User) -> String {
    format!("Hi {} {}!", user.first_name, user.last_name)
}

fn main() -> std::io::Result<()> {
    Application::new(router! {
        GET "/hi/:first_name/:last_name" => hi
        POST "/update_data" => update_age
    })
    .serve("0.0.0.0:3000")
}

路由器宏支持以下功能:

嵌套路由

路由可以嵌套。

router! {
    "/foo" => {
        GET "/bar" => bar
    }
}

URL参数

可以使用Path提取器捕获URI参数。

router! {
    GET "/users/:first/:last/:age" => greet
}

fn greet(Path((first, last, age)): Path<(String, String, u32)>) -> String {
    format!("Welcome {first} {last}. You are {age} years old.")
}

你可以使用NamedParam derive宏来定义命名参数。

router! {
    GET "/users/:first/:last/:age" => greet
}

#[derive(NamedParam)]
struct GreetInfo {
    first: String,
    last: String,
    age: u32,
}

fn greet(GreetInfo { first, last, age }: GreetInfo) -> String {
    format!("Welcome {first} {last}. You are {age} years old.")
}

或者,你可以直接使用Params提取器访问参数。

通配符

可以使用_语法来捕获通配符路由。

router! {
    "/foo" => {
        GET "/bar" => bar
        _ => matches_foo_but_not_bar
    }
    _ => not_found
}

守卫

路由可以由守卫来保护。

struct ContentLengthLimit(u64);

impl Guard for ContentLengthLimit {
    fn check(&self, req: &RequestContext) -> bool {
        // ...
    }
}

router! {
    "/short_requests" if ContentLengthGuard(128) => {
        POST "/super" if ContentLengthGuard(64) => super_short
        POST "/" => short
    }
}

守卫可以使用&&||语法进行链式调用。

中间件

中间件是任何调用请求上下文中的next_handler的处理器。像处理器一样,它可以使用提取器。

fn logger(req: RequestContext) -> Response {
    println!("Before");
    let result = req.next_handler();
    println!("After");
    result
}

fn main() -> std::io::Result<()> {
    Application::new(router! {
        with logger;

        GET "/" => hi
    })
    .serve("0.0.0.0:3000")
}

中间件可以链式连接,并放置在子路由中。

router! {
    with [mid1, mid2];

    "/foo" => {
        with [foo_mid1, foo_mid2];
    }
}

它们也可以针对单个路由。

router! {
    GET "/" with mid1 => home
}

测试

Lunatic提供了一个宏#[lunatic::test],可以将你的测试转换为进程。查看tests文件夹中的示例。

许可证

在以下任一许可证下授权:

由你选择。

依赖关系

~6.5–9.5MB
~178K SLoC