OpenAPI
With the openapi feature, Kerniq serves an OpenAPI document generated by
Utoipa and, optionally, a Swagger UI page.
toml
kerniq-server = { version = "0.1", features = ["openapi"] }
utoipa = "6"Utoipa's derive macros generate the document at compile time from your types
and #[utoipa::path] annotations. Kerniq does not generate or infer the
document itself.
rust
use kerniq_server::openapi::OpenApiDocs;
use kerniq_server::prelude::*;
use serde::Serialize;
use utoipa::{OpenApi, ToSchema};
#[derive(Serialize, ToSchema)]
struct Account {
id: u64,
/// Balance in minor units (cents).
balance_minor: i64,
}
/// Fetch an account.
#[utoipa::path(
get,
path = "/accounts/{id}",
params(("id" = u64, Path, description = "Account id")),
responses(
(status = 200, body = Account),
(status = 404, description = "No such account"),
)
)]
async fn get_account(Path(id): Path<u64>) -> Json<Account> {
Json(Account { id, balance_minor: 0 })
}
#[derive(OpenApi)]
#[openapi(
info(title = "Accounts API", version = "1.0.0"),
paths(get_account),
components(schemas(Account))
)]
struct ApiDoc;
#[tokio::main]
async fn main() -> Result<()> {
let docs = OpenApiDocs::new(ApiDoc::openapi())
.json_path("/openapi.json") // default
.swagger_ui("/docs"); // optional
App::new()
.get("/accounts/{id}", get_account)
.merge(docs.into_router())
.run("127.0.0.1:3000")
.await
}GET /openapi.jsonreturns the document, serialized once at startup.GET /docsreturns a Swagger UI page that loadsswagger-ui-dist(pinned tokerniq_server::openapi::SWAGGER_UI_VERSION) from the unpkg CDN.
For environments without internet access, use utoipa-swagger-ui, which
embeds the assets, and mount it with App::mount_axum.
Keep the #[utoipa::path] path in sync with the registered route: Utoipa
documents the path you declare, and Kerniq does not cross-check the two.