18 个版本 (4 个重大变更)
0.5.2 | 2024 年 4 月 26 日 |
---|---|
0.5.1 | 2024 年 4 月 26 日 |
0.4.6 | 2024 年 4 月 26 日 |
0.3.2 | 2024 年 4 月 20 日 |
0.1.1 | 2024 年 4 月 18 日 |
#505 在 HTTP 服务器
每月下载量 132
33KB
510 行
功能
基于 salvo 和 sea-orm 封装的现成 Web 服务器框架。
使用数据库 (sea-orm)
-
在您的 Cargo.toml 中添加
sea-orm
依赖项 -
根据您需要的数据库类型启用以下功能之一或多个
- mysql
- sqlite
- postgres
- 运行以下命令,请参阅 sea-orm 文档
- sea-orm-cli generate entity -o src/model
- 将生成的模型导入您的
main.rs
文件
- mod model;
- 使用的数据库可以在
config.toml
中配置
使用 Http3
启用 http3
功能并在 config.toml
中配置相关证书
示例
use webserver_rs::prelude::*;
use salvo::prelude::*;
use salvo::jwt_auth::HeaderFinder;
use serde::{Deserialize, Serialize};
use serde_json::json;
use tokio::io::AsyncReadExt;
use webserver_rs::{
MemoryStream, authorization, build_cros, config::Config, expire_time, html_err,
json_err, router, FromConfigFile, HttpResult,
};
use webserver_rs::web_core::authorization::gen_token;
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "serde")]
struct JwtClaim {
username: String,
exp: i64, // required
}
#[handler]
pub fn hello(req: &mut Request, res: &mut Response) -> HttpResult<()> {
let c = req.query::<String>("id");
println!("{c:?}");
let p = req.query::<String>("id").ok_or(html_err!(
400,
json!({
"status":"fail",
"msg":"id not found"
})
.to_string()
))?;
res.render(Text::Plain(format!("hello, {p}")));
Ok(())
}
#[handler]
pub fn login(depot: &mut Depot, res: &mut Response) -> HttpResult<()> {
let config = depot.obtain::<Config>().map_err(|_e| {
crate::json_err!(400,{
"status":"fail",
"msg":"config not found"
})
})?;
let token = gen_token(
config.secret_key.clone(),
JwtClaim {
exp: crate::expire_time!(Days(1)),
username: "a".to_string(),
},
)
.map_err(|e| crate::json_err!(400, {"err":e.to_string()}))?;
res.render(Text::Plain(token));
Ok(())
}
#[handler]
pub async fn image(res: &mut Response) -> HttpResult<()> {
let mut file = tokio::fs::File::open("./test.png")
.await
.map_err(|_| crate::html_err!(404, ""))?;
let mut s = Vec::new();
file.read_to_end(&mut s).await.unwrap();
res.stream(MemoryStream::new(s, 200));
Ok(())
}
#[handler]
pub async fn text_json(res: &mut Response) -> HttpResult<()> {
res.render(Text::Json(
json!({
"title":1
})
.to_string(),
));
Ok(())
}
mod ab {
use salvo::handler;
#[handler]
pub fn show() -> &'static str {
"abc"
}
pub mod shop {
#[super::handler]
pub fn show() -> &'static str {
"show"
}
}
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = Config::from_config_file("./config.toml").expect("config file not found");
let jwt = authorization::gen_jwt_auth::<JwtClaim>(
config.secret_key.clone(),
vec![Box::new(HeaderFinder::new())],
);
webserver_rs::serve_routes! {
config =>[
// https://127.0.0.1:8080/hello
router!([get, post] => @hello)
.hoop(jwt)
.hoop(authorization::AuthGuard::new(|_e| html_err!("unauthorized"))),
// https://127.0.0.1:8080/user/login
router!([get] => /user/@login),
// https://127.0.0.1:8080/a/b/show
router!([get, post] => a/b/@ab::show),
// https://127.0.0.1:8080/b/c/show/*
router!([get, post, put] => /b/c/@ab::show/<**path>),
// https://127.0.0.1:8080/test_json
router!([get, post] => @text_json).hoop(build_cros("*")),
// https://127.0.0.1:8080/ab/shop/show
router!([get, post] => ...@ab::shop::show).hoop(build_cros("*")),
] // (& [middlewares,])?
};
Ok(())
}
依赖项
~34–58MB
~1M SLoC