23个版本 (重大更新)

0.19.1 2020年12月25日
0.18.0 2020年6月13日

#10 in #home

Download history 2/week @ 2024-03-26 19/week @ 2024-04-02

每月69次 下载

BSD-3-Clause

36KB
762

用Rust编写的自制Web框架

您看到的是我的自制Web框架。它最初是一个宠物项目,可能还会继续是,但现在它已经有了足够的特性来创建简单的网页,它甚至有模板。

它是否适合生产环境?绝对不是。它没有转义功能。它不解析输入头。没有中间件。可以列举很多。

但是,我有一个个人页面运行在这个框架上,地址是 http://glotitude.datamonkey.pro/。欢迎查看。

快速开始

  • 您应该使用nightly构建,因为 concat_idents!
  • 向ctchi框架添加依赖项
[dependencies]
ctchi = "0.18.0"
ctchi_codegen = "0.2.0"
regex = "1"
  • 编写您的控制器和主函数。您需要以下所有导入
#![feature(concat_idents)]
#[macro_use]
extern crate ctchi;

use ctchi::core::app::Ctchi;
use ctchi::core::routes::{Routes, Route};

use ctchi_codegen::route;

#[route("/")]
fn index() -> String {
    render!("index.html")
}

fn main() {
    let mut routes = Routes::new();
    // add route to your controller
    routes.add_route(routes!(index)());

    // create and run local server
    let server = Ctchi::new(routes);
    let server_result = match server.start() {
        Ok(()) => "Ctchi application server is successfully running!".to_string(),
        Err(err) => format!("Can't start server! Because '{}'", err)
    };
}
  • 运行它 :)
cargo run

配置

Ctchi只有少数配置选项

  1. bind_path - 服务器(默认为 127.0.0.1:8080)的IP地址和端口号
  2. base_path - 模板文件夹的路径(默认为当前目录 + /src/pages/
  3. static_uri_pref - 静态文件(CSS/JS/图片等)的URL前缀(默认为 static
  4. log_path - 日志文件的文件系统路径。

有几种方法可以更改服务器的配置

更改配置文件

您应该在 /etc/ctchi/conf.txt 创建它。您只能覆盖那里的2个属性 bind_pathbase_path

配置单例

您可以通过导入 use ctchi::core::config::get_configuration; 在程序中的任何位置获取ctchi配置。然后您可以得到配置的读取器和互斥锁

// get reader
let config_reader = get_configuration();
// get mutex
let config = config_reader.inner.lock().unwrap();
// read some propeties
let prefix = &config.static_uri_pref;
// drop mutex
drop(config);

drop 非常重要。你可以省略它,它会在作用域结束时自动调用,但如果你在作用域内尝试获取另一个配置,程序将无法工作。所以,如果你绝对确定不会对配置进行第二次调用,就不需要 drop,否则最好显式调用它。

模板

Ctchi 有 HTML 模板引擎。它并不复杂,但具备你需要的所有核心功能。它有哪些标签。

  1. [template][endtemplate]
  2. [for i in values][endfor]
  3. [if value][endif]
  4. [code][endcode]
  5. [import "./base.html" /]
  6. [[value]]

[template] 是根标签,如果你的页面有它,则它是一个带有标签的 HTML 页面,否则 ctchi 会将其视为纯 HTML 页面。

[for] 标签用于循环。你可以在上下文中传递值(字符串向量),它会根据值的长度多次写入内部部分。

[if] 从上下文中获取布尔值,并在值为真时写入内部块。它没有 else 子句。它不能接受表达式。因此,所有逻辑都应该在后端。

[code] 将作用域内的所有内容视为纯 HTML。对于长代码片段来说很棒,因为你不需要在每个方括号中转义。

[import] 从指定的页面获取页面并将其导入当前模板。所有关于标签的规则也适用于该页面。

[[value]]。纯值或 for 循环的变量应该用双大括号括起来。

除了 import 和 value 标签之外,每个标签都应该有结束部分。

日志记录

如果你想要记录你的请求和响应的日志,你应该在你的主函数中添加 logger.init。

use ctchi::log::logger;

fn main() {
    logger::init();
    // ... other code
}

配置有一个 log_path 字段,你可以通过配置文件或配置对象来更改它 :)

fn main() {
    // ... other code
    let config_reader = get_configuration();
    let mut config = config_reader.inner.lock().unwrap();
    config.log_path = "/Users/glotitude/log/ctchi/server.log".to_string();
    drop(config);
    // ... other code
}

示例

记住,所有 HTML 页面默认应该放在 src/pages 文件夹中。现在,比如说,我们每个页面都有一个相同的页眉。让我们将它放在 header.html

<head>
    <meta charset="UTF-8">
    <title>Imported Header</title>
    <link href="/static/css/main.css" type="text/css" rel="stylesheet">
</head>

我们还有 index.html

[template]
<html lang="en">
    [import "header.html"/]
<body>
[if authorized]
    Hello [[user_name]].
[endif]

Your options for today are:
<ul>
[for option in options]
    <li>[[option]]</li>
[endfor]
</ul>
</body>
</html>
[endtemplate]

所以,我们的控制器会如何寻找这样的模板

#[route("/")]
fn index()-> String {
    let mut context = HashMap::<String, Context>::new();
    context.insert("authorized".to_string(), Context::BooleanValue(true));
    context.insert("user_name".to_string(), Context::SingleValue("Leonid Toshchev".to_string()));
    context.insert("options".to_string(), Context::MultiValue(vec!("Eat".to_string(), "Code".to_string(), "Sleep".to_string())));
    render!("index.html", context)
}

依赖项

~4–6MB
~107K SLoC