What the Axum generator creates
openapi-to-rust is a spec-first Axum generator: the input is an OpenAPI YAML or JSON document and the output is Rust server scaffolding. For selected operations, it emits:
- A service trait per OpenAPI tag.
- A typed response enum per operation, with variants tied to documented status codes.
- Axum handlers and a combined
build_router(...)factory. - Path, query, header, and request-body extraction.
- An HTTP 400 short-circuit when required parameters are missing or invalid at the handler boundary.
- SSE-ready response variants when streaming behavior is declared.
Shared request and response models live in the same generated types.rs used by the optional client. Your implementation remains ordinary Rust behind the generated trait.
Select the operations your server hosts
Add a [server] section to openapi-to-rust.toml:
[generator]
spec_path = "openapi.yaml"
output_dir = "src/generated"
module_name = "api"
[features]
enable_async_client = false
[server]
framework = "axum"
operations = [
"createResponse",
"GET /v1/responses/{response_id}",
"tag:Files",
]
prune_models = trueSelectors accept an exact operationId, an exact METHOD /path, or an entiretag:name. With prune_models = true, schemas unreachable from the selected surface are omitted.
Use the CLI to inspect and update the selection without hand-editing TOML:
openapi-to-rust server list --tag Responses
openapi-to-rust server add createResponse
openapi-to-rust server add --all-tag Files
openapi-to-rust server remove deleteFile
openapi-to-rust generateImplement the generated Axum trait
Implement each selected operation on your application state, then pass that state to the generated router factory. The exact types come from the OpenAPI contract, while authorization, storage, orchestration, and domain behavior remain yours.
use generated::server::{
build_router, CreateResponseResponse, ResponsesApi,
};
#[derive(Clone)]
struct AppState;
#[axum::async_trait]
impl ResponsesApi for AppState {
async fn create_response(
&self,
body: CreateResponse,
) -> CreateResponseResponse {
CreateResponseResponse::Ok(build_response(body))
}
}
let app = build_router(AppState);Tags let a larger service split implementation across focused traits. The combined router joins the selected tag routers so the application can serve one Axum Router.
Return status-code-typed responses
Instead of returning an unstructured status and body pair, each generated operation exposes an enum whose variants correspond to documented responses. A successful JSON response, a typed 4xx body, and an empty 204 become distinct Rust variants.
This makes the implementation’s possible wire responses visible in its return type. It does not add general runtime schema validation: minimums, maximums, patterns, and similar constraints are included as documentation rather than validators.
Generate SSE-ready Axum responses
When an operation declares text/event-stream, the response enum can include an SSE stream variant. The generatedsse_response helper accepts a stream of Axum SSE events and produces the payload expected by that variant.
Some public API documents omit streaming media types even when the live API supports them. Use a small overlay to add the missing response content entry before generation. The included Anthropic Messages example uses this approach rather than maintaining a full fork of the upstream document.
Generate a client and server together
You can enable the async client and Axum server in the same configuration. Client and server selectors are independent, and model pruning retains schemas reachable from either selected surface. This works well for gateways, protocol adapters, and services that host part of an API while calling another part.
See the completeOpenAI Responses examplefor multi-tag routing, request bodies, SSE, query parameters, and required-parameter handling.
Current server-generation limits
- Axum is the only generated server framework.
- Server generation is opt-in and the crate is pre-1.0.
- OpenAPI 2.0 is not accepted.
- Modeling a security scheme does not generate your authorization policy or credential storage.
- OpenAPI 3.2 support is experimental; verify generated behavior for less-common fields.
Compare this workflow with OpenAPI Generator’s separate beta rust-axum target in thesource-linked Rust generator comparison.