2个版本

0.0.2 2023年10月19日
0.0.1 2023年8月16日

#470 in HTTP服务器

MIT 许可证

120KB
2.5K SLoC

YAHF

另一个HTTP框架

警告:YAHF只在nightly版本下工作,直到RPITIT稳定

YAHF的目标是提供良好的开发者体验,并且易于扩展。

目录

功能

  • 无宏路由API
  • 可预测的错误处理
  • 处理器内建的本地序列化和反序列化
  • 友好的语法

示例

Hello world的YAHF是

use yahf::server::Server;

#[tokio::main]
async fn main() {
 let server = Server::new().get(
     "/",
     || async { "Hello world".to_string() },
     &(),
     &String::with_capacity(0),
 );

 server
     .listen(([127, 0, 0, 1], 8000).into())
     .await
     .unwrap();
}

路由

Router用于将处理器绑定到路径。

use yahf::router::Router;

// Router
let router = Router::new()
 .get("/", root_get, &(), &())
 .get("/foo", foo_get, &(), &())
 .post("/foo", foo_post, &(), &())
 .delete("/foo/bar", bar_delete, &(), &());

// calls respectively each of these handlers

async fn root_get() {}
async fn foo_get() {}
async fn foo_post() {}
async fn bar_delete() {}

ServerRouter继承这些功能。

处理器

在YAHF上,一个handler是一个用于处理Route的异步函数。一个可接受的handler实现了Runner特质。默认支持以下签名

async fn handler1() -> ResponseBody  {todo!()}
async fn handler2() -> Response<ResponseBody>  {todo!()}
async fn handler3(req: RequestBody) -> ResponseBody  {todo!()}
async fn handler4(req: Request<RequestBody>) -> ResponseBody {todo!()}
async fn handler5(req: RequestBody) -> Response<ResponseBody> {todo!()}
async fn handler6(req: Request<RequestBody>) -> Response<ResponseBody> {todo!()}
async fn handler7() -> Result<ResponseBody> {todo!()}
async fn handler8() -> Result<Response<ResponseBody>> {todo!()}
async fn handler9(req: Result<RequestBody>) -> Result<ResponseBody> {todo!()}
async fn handler10(req: Result<Request<RequestBody>>) -> Result<ResponseBody> {todo!()}
async fn handler11(req: Result<RequestBody>) -> Result<Response<ResponseBody>> {todo!()}
async fn handler12(req: Result<Request<RequestBody>>) -> Result<Response<ResponseBody>> {todo!()}

所有这些签名都来自RunnerInputRunnerOutput的实现。

可扩展性

YAHF handlers 是按模块化设计的。一个 handler 被分解为四个模块:一个正文 deserializer,一个正文 serializerarguments,以及一个 response。这些模块通过 Runner 特性粘合在一起。向处理器添加新功能只需实现这些特性之一。有关更多详细信息,请查看特性文档

中间件

Middleware 是异步函数,将在 handler 之前或之后运行。当与 RouterServer 结合使用时,这些函数非常有用,可以重用逻辑并创建 "pipelines"

示例```rust use serde::Deserialize; use serde::Serialize; use yahf::handler::Json; use yahf::request::Request; use yahf::result::Result; use yahf::response::Response; use yahf::router::Router; use yahf::server::Server;

use std::time; use std::time::UNIX_EPOCH; #[derive(Debug, Deserialize, Serialize)] struct ComputationBody { value: u32, }

// 打印时间、方法和请求的路径 async fn log_middleware(req: Result<Request>) -> Result<Request> { match req.into_inner() { Ok(req) => { println!( "{} - {} - {}", time::SystemTime::now() .duration_since(UNIX_EPOCH) .expect("Negative time") .as_millis(), req.method().as_str(), req.uri().path() );

        Ok(req).into()
    }
    Err(err) => Err(err).into(),
}

}

// 处理任何可能的错误 async fn log_error(res: Result<Response>) -> Result<Response> { match res.into_inner() { Err(err) => { println!( "{} - {}", time::SystemTime::now() .duration_since(UNIX_EPOCH) .expect("Negative time") .as_millis(), err.code(), ); Err(err).into() } ok => ok.into(), } }

// 使用 ComputationBody 计算某些内容 async fn some_computation(req: ComputationBody) -> ComputationBody { ComputationBody { value: req.value + 1, } }

// 设置一个具有 MiddlewaresRouter。// 路由 / 将成为:log_middleware -> some_computation -> log_middleware let router = Router::new() .pre(log_middleware) .after(log_error) .get("/", some_computation, &Json::new(), &Json::new()); ``` 更多示例 这里

示例

该存储库包含 说明示例,展示了所有组件的集成

版本 1.0.0 的目标

YAHF 遵循 SemVer

版本 1.0.0 的目标是拥有一个稳定的项目,可以处理现实世界的问题,具有良好的开发者体验,并且可以扩展项目以满足任何需求。

本版本的目标特性包括

  • 可组合的路由系统;
  • 中间件函数;
  • 支持或不支持安全的 HTTP/1.1。

依赖关系

~14–26MB
~471K SLoC