Runtime
OpenAPI
OpenAPI route metadata and document rendering.
OpenAPI
nidus-openapi records route metadata and renders OpenAPI JSON.
#[derive(utoipa::ToSchema)]
struct UserDto {
id: i32,
email: String,
}
#[derive(utoipa::ToSchema)]
struct CreateUserDto {
email: String,
}
let document = OpenApiDocument::new("Nidus API", "1.0.0")
.schema::<CreateUserDto>()
.schema::<UserDto>()
.route(
OpenApiRoute::post("/users")
.summary("Create user")
.tag("users")
.response_status(StatusCode::CREATED)
.request_schema::<CreateUserDto>()
.response_schema::<UserDto>(),
);
Use .tag("...") to group operations in generated OpenAPI tooling. Multiple tags can be attached to the same route. Manual OpenAPI route builders accept Nidus-style :id parameters and normalize them to OpenAPI {id} path parameters. Parameter segments are emitted as required OpenAPI path parameters with string schemas. Use try_get, try_post, try_put, try_patch, or try_delete when invalid paths should return a RoutePathError. Operations receive stable operationId values derived from the HTTP method and normalized path, such as get_users_by_id for GET /users/{id}. Use .request_schema::<T>() and .response_schema::<T>() with OpenApiDocument::schema::<T>() to reference JSON DTO schemas generated by utoipa::ToSchema. Use .response_status(StatusCode::CREATED) when the successful response should be documented under a status other than 200.
Route macros can emit the same operation tags through #[openapi] metadata:
#[get("/:id")]
#[openapi(
summary = "Find user by ID",
tags = ["users", "read"],
status = 200,
response = UserDto
)]
async fn find_one(&self) {}
Macro metadata currently supports summary = "..." and optional tags = ["..."], status = 201, request = Type, and response = Type. Unsupported keys fail at compile time, and the cargo nidus openapi inspector reports the same error when reading source files. The inspector defaults to info.title = "Nidus API" and info.version = "1.0.0"; pass --title and --version to emit application-specific document metadata:
cargo nidus openapi --title "Users API" --version "1.2.3"
Generated OpenAPI operations also preserve Nidus route annotations as vendor extensions: x-nidus-guards, x-nidus-pipes, and x-nidus-validates. When cargo nidus openapi discovers request = Type or response = Type, it emits matching $ref values and inspects local named DTO structs for simple field-level schemas. Primitive fields, Option<T>, Vec<T>, and nested local DTO structs are handled directly, and common serde field metadata such as rename, default, and skip is respected. Unsupported shapes fall back to object schemas. Use the runtime OpenApiDocument::schema::<T>() builder path when the output needs the full utoipa::ToSchema model.
Generated route metadata can also seed a document directly:
let document = OpenApiDocument::from_controller_routes(
"Nidus API",
"1.0.0",
UsersController::controller_prefix(),
&UsersController::routes(),
);
For multiple controllers, use the builder form:
let document = OpenApiDocument::new("Nidus API", "1.0.0")
.controller_routes(UsersController::controller_prefix(), &UsersController::routes())
.controller_routes(AdminController::controller_prefix(), &AdminController::routes());
This keeps controller prefixes and route paths explicit while reusing the same normalization rules as the HTTP router. Use try_from_route_metadata, try_from_controller_routes, try_controller_routes, try_schema, or try_schemas_from_route_metadata when composing metadata from generated or external sources where invalid paths, duplicate path/method operations, or schema registration failures should return an OpenApiDocumentError instead of panicking. The infallible builder methods panic on those errors rather than silently overwriting an existing operation or dropping schemas.
Serve the generated OpenAPI document and interactive documentation from an Axum router:
let router = document.into_router();
This exposes /openapi.json and /docs. The docs page loads Swagger UI in the browser and points it at the local OpenAPI JSON route.