[![crates.io](https://img.shields.io/crates/v/spring-web.svg)](https://crates.io/crates/spring-web) [![Documentation](https://docs.rs/spring-web/badge.svg)](https://docs.rs/spring-web) [Axum](https://github.com/tokio-rs/axum)是rust社区最优秀的Web框架之一,它是由tokio官方维护的一个基于[hyper](https://github.com/hyperium/hyper)的子项目。Axum提供了web路由,声明式的HTTP请求解析,HTTP响应的序列化等功能,而且能够与[tower](https://github.com/tower-rs)生态中的中间件结合。 ## 依赖 ```toml spring-web = { version = "" } ``` 可选的**features**: `http2`、`multipart`、`ws`。 ## 配置项 ```toml [web] binding = "172.20.10.4" # 要绑定的网卡IP地址,默认0.0.0.0 port = 8000 # 要绑定的端口号,默认8080 connect_info = false # 是否使用客户端连接信息,默认false graceful = true # 是否开启优雅停机, 默认false # web中间件配置 [web.middlewares] compression = { enable = true } # 开启压缩中间件 catch_panic = { enable = true } # 捕获handler产生的panic logger = { enable = true, level = "info" } # 开启日志中间件 limit_payload = { enable = true, body_limit = "5MB" } # 限制请求体大小 timeout_request = { enable = true, timeout = 60000 } # 请求超时时间60s # 跨域配置 cors = { enable = true, allow_origins = [ "*.github.io", ], allow_headers = [ "Authentication", ], allow_methods = [ "GET", "POST", ], max_age = 60 } # 静态资源配置 static = { enable = true, uri = "/static", path = "static", precompressed = true, fallback = "index.html" } ``` > **NOTE**: 通过上面的middleware配置可以集成tower生态中提供的中间件。当然如果你对tower生态非常熟悉,也可以不启用这些middleware,通过编写代码自行配置。下面是相关的文档链接: > * [tower](https://docs.rs/tower/latest/tower/) > * [tower-http](https://docs.rs/tower-http/latest/tower_http/) ## API接口 App实现了[WebConfigurator](https://docs.rs/spring-web/latest/spring_web/trait.WebConfigurator.html)特征,可以通过该特征指定路由配置: ```no_run, rust, linenos, hl_lines=6 10-18 #[tokio::main] async fn main() { App::new() .add_plugin(SqlxPlugin) .add_plugin(WebPlugin) .add_router(router()) .run() .await } fn router() -> Router { Router::new().typed_route(hello_word) } #[get("/")] async fn hello_word() -> impl IntoResponse { "hello word" } ``` 你也可以使用`auto_config`宏来实现自动配置,这个过程宏会自动将被过程宏标记的路由注册进app中: ```diff +#[auto_config(WebConfigurator)] #[tokio::main] async fn main() { App::new() .add_plugin(SqlxPlugin) .add_plugin(WebPlugin) - .add_router(router()) .run() .await } ``` ## 属性宏 上面例子中的[`get`](https://docs.rs/spring-macros/latest/spring_macros/attr.get.html)是一个属性宏,`spring-web`提供了八个标准HTTP METHOD的过程宏:`get`、`post`、`patch`、`put`、`delete`、`head`、`trace`、`options`。 也可以使用[`route`](https://docs.rs/spring-macros/latest/spring_macros/attr.route.html)宏同时绑定多个method: ```rust use spring_web::route; use spring_web::axum::response::IntoResponse; #[route("/test", method = "GET", method = "HEAD")] async fn example() -> impl IntoResponse { "hello world" } ``` 除此之外,spring还支持一个handler绑定多个路由,这需要用到[`routes`](https://docs.rs/spring-macros/latest/spring_macros/attr.routes.html)属性宏: ```rust use spring_web::{routes, get, delete}; use spring_web::axum::response::IntoResponse; #[routes] #[get("/test")] #[get("/test2")] #[delete("/test")] async fn example() -> impl IntoResponse { "hello world" } ``` ## 提取插件注册的Component 上面的例子中`SqlxPlugin`插件为我们自动注册了一个Sqlx连接池组件,我们可以使用`Component`从State中提取这个连接池,[`Component`](https://docs.rs/spring-web/latest/spring_web/extractor/struct.Component.html)是一个axum的[extractor](https://docs.rs/axum/latest/axum/extract/index.html)。 ```rust #[get("/version")] async fn mysql_version(Component(pool): Component) -> Result { let version = sqlx::query("select version() as version") .fetch_one(&pool) .await .context("sqlx query failed")? .get("version"); Ok(version) } ``` axum也提供了其他的[extractor](https://docs.rs/axum/latest/axum/extract/index.html),这些都被reexport到了[`spring_web::extractor`](https://docs.rs/spring-web/latest/spring_web/extractor/index.html)下。 ## 读取配置 你可以用[`Config`](https://docs.rs/spring-web/latest/spring_web/extractor/struct.Config.html)抽取toml中的配置。 ```rust #[derive(Debug, Configurable, Deserialize)] #[config_prefix = "custom"] struct CustomConfig { a: u32, b: bool, } #[get("/config")] async fn use_toml_config(Config(conf): Config) -> impl IntoResponse { format!("a={}, b={}", conf.a, conf.b) } ``` 在你的配置文件中添加相应配置: ```toml [custom] a = 1 b = true ``` 完整代码参考[`web-example`](https://github.com/spring-rs/spring-rs/tree/master/examples/web-example) ## 在Middleware中使用Component抽取注册的组件 你也可以在[middleware中使用Extractor](https://docs.rs/axum/latest/axum/middleware/fn.from_fn.html),注意需要遵循axum的规则。 ```rust use spring_web::{axum::{response::Response, middleware::Next}, extractor::{Request, Component}}; use spring_sqlx::ConnectPool; async fn problem_middleware(Component(db): Component, request: Request, next: Next) -> Response { // do something let response = next.run(request).await; response } ``` 完整代码参考[`web-middleware-example`](https://github.com/spring-rs/spring-rs/tree/master/examples/web-middleware-example)