5 个不稳定版本
0.6.0 | 2024年2月12日 |
---|---|
0.5.3 | 2023年5月18日 |
0.5.2 | 2023年5月18日 |
0.1.1 | 2023年3月3日 |
0.1.0 | 2023年3月3日 |
#3 in #独立
311 个月下载量
在 oasgen 中使用
3MB
271 行
oasgen
- OpenAPI规范生成器
oasgen
是一个库,可以从Rust服务器代码(或任何异步函数)生成OpenAPI 3.0规范。它支持
actix
- actix-webaxum
- axum- 无框架 - 如果您只想将Rust函数注册以生成OpenAPI规范文件。
欢迎为支持其他Web框架做出贡献!
示例
// Actix-web example
use actix_web::web::Json;
use actix_web::{App, HttpServer};
use oasgen::{oasgen, OaSchema, Server};
use serde::{Deserialize, Serialize};
#[derive(OaSchema, Deserialize)]
pub struct SendCode {
pub mobile: String,
}
#[derive(Serialize, OaSchema, Debug)]
pub struct SendCodeResponse {
pub found_account: bool,
}
#[oasgen]
async fn send_code(_body: Json<SendCode>) -> Json<SendCodeResponse> {
Json(SendCodeResponse {
found_account: false,
})
}
#[tokio::main]
async fn main() {
let server = Server::actix().post("/send-code", send_code).freeze();
HttpServer::new(move || App::new().service(server.clone().into_service()))
.bind(("127.0.0.1", 5000))
.unwrap()
.run()
.await
.unwrap()
}
// axum example
use oasgen::{OaSchema, Server, oasgen};
use axum::{Json, routing};
use serde::{Deserialize, Serialize};
#[derive(OaSchema, Deserialize)]
pub struct SendCode {
pub mobile: String,
}
#[derive(Serialize, OaSchema, Debug)]
pub struct SendCodeResponse {
pub found_account: bool,
}
#[oasgen]
async fn send_code(_body: Json<SendCode>) -> Json<SendCodeResponse> {
Json(SendCodeResponse { found_account: false })
}
#[tokio::main]
async fn main() {
let server = Server::axum()
.post("/send-code", send_code)
.freeze();
let router = axum::Router::new()
.route("/healthcheck", routing::get(|| async { "OK" }))
.merge(server.into_router());
axum::Server::bind(&"0.0.0.0:5000".parse().unwrap())
.serve(router.into_make_service())
.await
.unwrap();
}
要编译axum示例,请使用以下依赖项
[dependencies]
axum = "0.6"
oasgen = { version = "0.19.0", features = ["axum"] }
serde = { version = "1.0.196", features = ["derive"] }
tokio = { version = "1.36.0", features = ["full"] }
安装
[dependencies]
# At minimum, you probably want a server feature installed (axum, actix) to support that framework
oasgen = { version = "..", features = []}
有几个功能可用于激活其他库
actix
- actix-webaxum
- axumswagger-ui
- swagger uiuuid
- uuidchrono
- chronotime
- timesqlx
- sqlx
自定义生成的规范
您可以通过多种方式自定义生成的规范。
直接访问OpenAPI结构
您可以直接访问OpenAPI结构,因此您可以按需对其进行自定义。
let mut server = Server::new();
server.openapi.info.title = "My API".to_string();
server.openapi.components.schemas.insert("MySchema".to_string(), Schema::new_object());
server
.get("/my-route", my_handler)
.freeze();
请注意,您必须在调用 .freeze()
(该操作将OpenAPI结构移动到Arc以在线程间共享)之前进行任何更改。
自定义模式
您可以手动编写OaSchema的实现,而不是使用derive来自定义任何模式。如果这样做,请在结构定义之后调用 register_schema
以将其添加到规范中。
use oasgen::{OaSchema, Schema, register_schema};
pub struct User {
pub id: i32,
pub name: String,
}
impl OaSchema for User {
fn schema() -> Schema {
let mut schema = Schema::new_object();
schema.properties_mut().insert("id", Schema::new_integer());
schema.properties_mut().insert("name", Schema::new_string());
schema
}
}
register_schema!("User", &|| User::schema());
从技术上讲,您根本不需要实现OaSchema。您可以将任何返回 Schema
的任意闭包传递给register_schema宏。
您还可以自定义操作
async fn my_server_handler() {
// ...
}
// You must use the fully qualified path to the function.
// You can simplify this slightly by passing in `concat!(module_path!(), "::my_server_handler")`
register_operation!("my_server_crate::path::to::my_server_handler", &|| {
let mut operation = Operation::default();
operation.summary = Some("My summary".to_string());
// ...
operation
});
属性
oasgen
定义了自己的属性,并尊重 serde
属性。它还使用文档字符串作为描述。您可以在 macro/src/attr.rs
中查看所有属性。查看这些结构以获取相关文档,并查看下面的示例。
#[derive(OaSchema)]
pub struct User {
pub id: i32,
pub name: String,
// Because oasgen respects serde attributes, this will not appear in the spec.
#[serde(skip)]
pub password_hash: String,
// This will be in the response (because there's no serde(skip), but it will not show up in the OpenAPI spec.
#[oasgen(skip)]
pub internal_id: i32,
}
#[oasgen(
tags("auth", "users"),
summary = "This is a short summary"),
deprecated = true,
operation_id = "my_operation_id",
description = "This is a long description and will override the docstring of the function",
)]
async fn my_server_handler() {
// ...
}
将规范写入文件
您可以直接访问 OpenAPI
结构。您可以使用 serde
将其写入文件、stdout等。
我们提供了一个辅助函数 write_and_exit_if_env_var_set
,它可以很好地与基本构建过程集成。
let server = Server::new()
// your routes
.write_and_exit_if_env_var_set("./openapi.yaml")
// .freeze() here, if you're mounting to a server.
如果设置了 OASGEN_WRITE_SPEC=1
,它将把规范写入路径,然后退出。
在您的构建过程中,构建可执行文件,设置环境变量输出规范后运行一次,然后不设置环境变量再次运行以正常启动服务器。
显示规范的路由
[!注意]
需要swagger-ui
功能
有内置函数来创建显示原始规范的路由,或者显示规范的自定义 Swagger UI 页面。
let mut server = oasgen::Server::axum()
.post("/auth/register_password", auth::register_password) // example route
.route_yaml_spec("/openapi.yaml") // the spec will be available at /openapi.yaml
.route_json_spec("/openapi.json") // the spec will be available at /openapi.json
.swagger_ui("/openapi/"); // the swagger UI will be available at /openapi/.
// NOTE: The trailing slash is required, as is calling either `route_yaml_spec()` or `route_json_spec()` before `swagger_ui()`.
如果您需要自定义这些路由,可以直接使用 OpenAPI 结构的副本。它位于 Arc 中,因此克隆成本低。
let mut server = oasgen::Server::axum()
.post("/auth/register_password", auth::register_password) // example route
.freeze();
let spec = server.openapi.clone();
let router = axum::Router::new()
.merge(server.into_router())
.route("/alt/route/to/openapi.yaml", get(|| {
let spec = spec.clone();
async {
serde_yaml::to_string(spec).unwrap()
}
}))
;
依赖关系
~3–11MB
~95K SLoC