23个版本 (重大更新)
0.19.1 | 2020年12月25日 |
---|---|
0.18.0 | 2020年6月13日 |
#10 in #home
每月69次 下载
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只有少数配置选项
bind_path
- 服务器(默认为127.0.0.1:8080
)的IP地址和端口号base_path
- 模板文件夹的路径(默认为当前目录 +/src/pages/
)static_uri_pref
- 静态文件(CSS/JS/图片等)的URL前缀(默认为static
)log_path
- 日志文件的文件系统路径。
有几种方法可以更改服务器的配置
更改配置文件
您应该在 /etc/ctchi/conf.txt
创建它。您只能覆盖那里的2个属性 bind_path
和 base_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 模板引擎。它并不复杂,但具备你需要的所有核心功能。它有哪些标签。
- [template][endtemplate]
- [for i in values][endfor]
- [if value][endif]
- [code][endcode]
- [import "./base.html" /]
- [[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