openapi-to-rust
A Rust code generator that creates strongly-typed structs, HTTP clients, and SSE streaming clients from OpenAPI 3.1 specifications.
We originally built this internally at GPU CLI to generate typed Rust clients for OpenAI, Anthropic, and other APIs. After battle-testing it against real-world specs with complex union types, discriminated enums, and streaming endpoints, we decided to open source it.
Features
- OpenAPI 3.1 support — objects, arrays, enums,
oneOf,anyOf,allOf, discriminated unions - HTTP client generation — async clients with retry logic, tracing, and auth middleware
- SSE streaming clients — first-class Server-Sent Events support with reconnection
- Smart
$refresolution — handles circular references and deep nesting - Discriminator detection — auto-detects tagged unions from
oneOf/anyOfwith const properties - TOML configuration — declarative config as an alternative to the Rust API
- Snapshot testing — built-in
instasnapshot tests for generated output - Optional specta support — add
specta::Typederives for TypeScript codegen
Install
Add to your Cargo.toml:
[]
= "0.1"
Or install the CLI:
Quick Start
CLI (TOML config)
Create openapi-to-rust.toml:
[]
= "openapi.json"
= "src/generated"
= "api"
[]
= true
[]
= "https://api.example.com"
= 30
[]
= 3
[]
= "Bearer"
= "Authorization"
Then generate:
Library API
use ;
use PathBuf;
Generated Output
The generator produces up to four files:
| File | Description |
|---|---|
types.rs |
All struct/enum definitions from OpenAPI schemas |
client.rs |
Async HTTP client with typed methods per operation |
streaming.rs |
SSE streaming client with event parsing |
mod.rs |
Module declarations |
Generated Client Usage
use crateHttpClient;
use crate*;
async
HTTP Client Features
The generated HTTP client includes:
- All HTTP methods — GET, POST, PUT, DELETE, PATCH
- Retry with backoff — exponential backoff via
reqwest-retry(retries 429, 500, 502, 503, 504) - Distributed tracing — automatic request/response spans via
reqwest-tracing - Authentication — Bearer token, API key, or custom header auth
- Default headers — configurable per-client headers
- Middleware stack — composable request/response middleware
SSE Streaming
First-class support for Server-Sent Events endpoints:
use *;
let streaming_config = StreamingConfig ;
Discriminated Unions
Automatically detects and generates tagged enums from OpenAPI discriminator patterns:
# OpenAPI spec
MessageContent:
oneOf:
- $ref: '#/components/schemas/TextContent'
- $ref: '#/components/schemas/ImageContent'
discriminator:
propertyName: type
mapping:
text: '#/components/schemas/TextContent'
image: '#/components/schemas/ImageContent'
Generates:
Also handles untagged unions (anyOf without discriminator), allOf composition, extensible enums, and inline variant schemas.
TOML Configuration Reference
[]
= "openapi.json" # Path to OpenAPI spec (required)
= "src/generated" # Output directory (required)
= "types" # Module name (required)
[]
= true # Generate SSE streaming client
= true # Generate HTTP REST client
= false # Add specta::Type derives
[]
= "https://api.example.com"
= 30 # 1-3600
[]
= 3 # 0-10
= 500 # 100-10000
= 16000 # 1000-300000
[]
= true
[]
= "Bearer" # Bearer | ApiKey | Custom
= "Authorization"
[[]]
= "content-type"
= "application/json"
[]
= true # Override nullable detection
[]
= "chrono::DateTime<chrono::Utc>"
Testing
# Run all tests
# Run snapshot tests
# Review snapshot changes
Examples
The examples/ directory contains working examples for:
- Basic type generation
- HTTP client generation
- Discriminated unions and
anyOf/oneOfpatterns allOfcomposition- Inline objects and enums
- Nullable field handling
- Recursive schemas
- TOML configuration
Contributing
- Fork the repo
- Add your OpenAPI spec pattern to
examples/ortests/fixtures/ - Write a test using snapshot testing (
insta) - Run
cargo insta testand review the output - Submit a PR
License
MIT