2个版本

0.1.1 2024年4月7日
0.1.0 2024年3月4日

#600HTTP服务器

Download history 3/week @ 2024-05-17 2/week @ 2024-05-24 1/week @ 2024-06-28 6/week @ 2024-07-05

103 每月下载量

Apache-2.0

1MB
371

Parfait

Parfait (/pɑːrˈfeɪ/ par-FAY) 是最轻量级的Web应用程序框架。它旨在快速简单地进行入门,并能够扩展到复杂的应用程序。

Parfait依赖于几个库 - serde用于JSON和tokio用于异步。

目标

Parfait的目标是提供一种轻量级且强大的解决方案,用于在Rust中构建Web应用程序。虽然已经有像Rocket和Actix这样的成熟框架可用,但Parfait旨在提供一种独特的、针对特定用例和偏好的方法。

基于宏的方法

Parfait使用宏来定义getpost端点等。这一决定是为了简化定义HTTP路由和处理请求的过程。通过使用宏,开发者可以以简洁、可读的方式定义路由,减少样板代码并提高代码可维护性。此外,宏允许在编译时验证路由定义,从而在开发早期阶段捕捉错误。总的来说,宏的使用提高了开发者的生产力,并为构建Web应用程序的轻量级、开发者友好的解决方案做出了贡献。

与Rocket的比较

Rocket 是一个功能丰富的Rust Web框架,以其易用性和广泛的功能而闻名。它提供了一套强大的内置功能,包括路由、请求解析和响应生成,使其适用于各种Web应用程序。

相比之下,Parfait采取了一种更简约的方法,侧重于简洁和灵活性。虽然Rocket在提供全面的功能方面表现出色,但Parfait更注重轻量级和定制。它旨在为开发者提供更多对所使用组件的控制,从而在构建Web应用程序时提供更大的灵活性。

与Actix的比较

Actix 是一个基于演员的、高性能框架,用于在Rust中构建并发和可扩展的Web应用程序。它利用演员模型来实现高并发和异步处理,使其适用于性能要求较高的应用程序。

与Actix不同,Parfait不采用actor模型,也不优先考虑达到相同的并发性和可扩展性。相反,它注重简单易用,同时仍然为大多数Web应用程序提供足够的性能。Parfait旨在让刚开始使用Rust进行Web开发的开发者易于上手,提供直观的抽象和清晰的文档。

如何使用

  1. 输入和输出结果
// Define a handler for the input form
get!("/", home_handler => r#"src\input.html"#, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");

// Define a handler for the result page
post!("/result", result_handler => "src/output.html", "text/html"); // For HTML response
...
get_handler: Some(|path, query| home_handler(path, query, None)),
post_handler: Some(|path, query, body| result_handler(path, query, Some(body))),

注意 Handler中的字段可以接受None类型。例如

....
let handler = Handler {
    get_handler: Some(|path, query| home_handler(path, query, None)),
    post_handler: Some(|path, query, body| result_handler(path, query, Some(body))),
};

更多详情请参考这里

  1. 循环
post!("/loop", result_handler => r#"examples\test5\loop.html"#, "text/html");
...
post_handler: Some(|_, _, _| {
    // Read the file content
    match std::fs::read_to_string("examples\\test5\\loop.html") {
        Ok(file_content) => {
            let items = vec!["Item 1", "Item 2", "Item 3"];
            let mut result = String::new();
            let mut in_for_loop = false;
            
            for line in file_content.lines() {
                if line.contains("{% for item in items %}") {
                    in_for_loop = true;
                    for item in &items {
                        result.push_str(&line.replace("{% for item in items %}", &format!("{}", item)));
                        result.push_str("\n");
                    }
                } else if in_for_loop && line.contains("{% endfor %}") {
                    in_for_loop = false;
                }
            }
            Some(format!("HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n{}", result))
        },
        Err(_) => Some("HTTP/1.1 500 INTERNAL SERVER ERROR\r\n\r\nFailed to read file".to_owned()),
    }
}),

更多详情请参考这里

  1. 使用URL路径
// Define a handler for the input form
get!("/hello/", home_handler => r#"src\input.html"#, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n");

// Define a handler for the result page
post!("/hello/result", result_handler => r#"src\output.html"#, "text/html");
  1. JSON
post!("/path", handle_post => r#"src\file.json"#, |_, _| {
    match std::fs::read_to_string("src\\file.json") {
        Ok(content) => {
            if let Some(json_data) = paprika::parse_json(&content) {
                let response_json = paprika::generate_json_response(json_data);
                Some(format!("HTTP/1.1 200 OK\r\nContent-Type: application/json\r\n\r\n{}", response_json))
            } else {
                Some("HTTP/1.1 500 INTERNAL SERVER ERROR\r\n\r\nFailed to parse JSON".to_owned())
            }
        },
        Err(_) => Some("HTTP/1.1 500 INTERNAL SERVER ERROR\r\n\r\nFailed to read file".to_owned()),
    }
});

更多详情请参考这里

功能

✅ post

✅ get

✅ put

✅ delete

✅ 处理get/post请求

✅ 与serde等第三方库兼容,如用于JSON

✅ 错误处理

✅ JSON

✅ 与查询一起工作

✅ 中间件

贡献

贡献绝对是受到欢迎和鼓励的!贡献有多种形式。您可以

  1. 通过问题提交功能请求或错误报告。
  2. 通过问题请求改进文档。
  3. 对需要反馈的问题发表评论。
  4. 通过拉取请求贡献代码。

许可证

Parfait遵循Apache许可证2.0版。请参阅LICENSE文件。

依赖

~3–9.5MB
~92K SLoC