Expand description
§tonic-rest-openapi
OpenAPI 3.1 spec generation and patching from protobuf descriptors for Tonic gRPC services.
Part of the tonic-rest ecosystem — define your API once in proto files, get gRPC, REST, and OpenAPI 3.1.
Reads compiled protobuf FileDescriptorSet bytes and a gnostic-generated OpenAPI YAML spec,
then applies a configurable pipeline of transforms to produce a clean OpenAPI 3.1 spec that
matches the runtime REST behavior.
§Key Features
- Proto as single source of truth — OpenAPI spec derived from the same proto files that drive gRPC and REST
- 12-phase transform pipeline — produces a clean OpenAPI 3.1 spec with security, validation constraints, and SSE annotations
- Google error model — injects structured error schemas matching runtime
RestErrorJSON responses - Security built-in — auto-generates Bearer JWT security scheme with public endpoint overrides
- Library + CLI — use programmatically in your build pipeline or as a standalone CI tool
§Pipeline
The 12-phase transform pipeline:
| Phase | Transform |
|---|---|
| 1 | Structural (3.0 → 3.1 upgrade, server/info injection) |
| 2 | SSE streaming annotations + Last-Event-ID header |
| 3 | Response fixes (empty→204, plain text, redirects, error schemas, 201 Created) |
| 4 | Enum value rewrites (strip UNSPECIFIED, normalize values) |
| 5 | Unimplemented (501) and deprecated operation markers |
| 6 | Security (Bearer JWT, public endpoint overrides) |
| 7 | Cleanup (tags, empty bodies, unused schemas, format: enum removal) |
| 8 | UUID wrapper flattening (path templates, $ref inlining, query params) |
| 9 | Validation constraints + field access annotation + Duration rewriting |
| 10 | Path field stripping + path parameter enrichment |
| 11 | Request body inlining + orphan removal |
| 12 | CRLF → LF normalization |
Each phase can be individually enabled/disabled via PatchConfig or ProjectConfig.
§Usage
§As a Library
use tonic_rest_openapi::{PatchConfig, ProjectConfig, discover, patch};
// From a config file
let project = ProjectConfig::load(Path::new("api/openapi/config.yaml"))?;
let metadata = discover(&descriptor_bytes)?;
let config = PatchConfig::new(&metadata).with_project_config(&project);
let patched_yaml = patch(&input_yaml, &config)?;Or configure programmatically:
let config = PatchConfig::new(&metadata)
.unimplemented_methods(&["SetupMfa", "DisableMfa"])
.public_methods(&["Login", "SignUp"])
.bearer_description("JWT access token")
.error_schema_ref("#/components/schemas/ErrorResponse");
let patched_yaml = patch(&input_yaml, &config)?;§As a CLI
# Full pipeline: lint → generate → patch
tonic-rest-openapi generate --config api/openapi/config.yaml --cargo-toml Cargo.toml
# Standalone patch
tonic-rest-openapi patch --config api/openapi/config.yaml --input spec.yaml --output patched.yaml
# Discover proto metadata
tonic-rest-openapi discover --descriptor file_descriptor_set.binEnable the cli feature for the binary:
[dependencies]
tonic-rest-openapi = { version = "0.1", features = ["cli"] }§Feature Flags
| Feature | Default | Description |
|---|---|---|
cli | off | CLI binary with generate, patch, discover, inject-version subcommands (adds clap, toml, anyhow) |
§Project Config File
# api/openapi/config.yaml
error_schema_ref: "#/components/schemas/ErrorResponse"
unimplemented_methods:
- SetupMfa
public_methods:
- Login
- SignUp
plain_text_endpoints:
- path: /health/live
example: "OK"
metrics_path: /metrics
readiness_path: /health/ready
transforms:
upgrade_to_3_1: true
annotate_sse: true
inject_validation: true
add_security: trueFor a complete end-to-end example with proto files, build.rs, REST handlers, and OpenAPI generation,
see auth-service-rs.
§Companion Crates
| Crate | Purpose | Cargo section |
|---|---|---|
| tonic-rest-core | Shared descriptor types | internal |
| tonic-rest | Runtime types | [dependencies] |
| tonic-rest-build | Build-time codegen | [build-dependencies] |
| tonic-rest-openapi (this) | OpenAPI 3.1 generation | CLI / CI |
§Dependencies
This crate uses serde_yaml_ng for YAML parsing
and serialization. serde_yaml_ng is a maintained fork of the archived serde_yaml crate.
While it is the best available option today, be aware that its ecosystem adoption is narrower
than serde_json. If a more widely-adopted YAML serde library emerges in the future,
migration may be warranted.
§Compatibility
| tonic-rest-openapi | tonic-rest-core | prost | MSRV |
|---|---|---|---|
| 0.1.x | 0.1 | 0.14 | 1.85 |
§License
MIT OR Apache-2.0
§API Reference
Structs§
- Contact
Info - Contact information for the
OpenAPIinfo.contactblock. - Enum
Rewrite - Enum value rewrite for a schema field whose runtime serde strips prefixes.
- External
Docs Info - External documentation link for
externalDocs. - Field
Constraint - A single field’s validation constraints, mapped to JSON Schema.
- Info
Overrides - Overrides for the
OpenAPIinfoblock. - License
Info - License information for the
OpenAPIinfo.licenseblock. - Operation
Entry - Maps a short proto method name to its gnostic operation ID.
- Patch
Config - Configuration for the
OpenAPIpatch pipeline. - Path
Param Constraint - Constraint for a single path parameter.
- Path
Param Info - Path parameter constraint info for a specific HTTP endpoint.
- Plain
Text Endpoint - An endpoint that returns plain text instead of JSON.
- Project
Config - Project-level
OpenAPIgeneration config. - Proto
Metadata - All RPC metadata extracted from proto descriptors.
- Schema
Constraints - Validation constraints for all fields in one schema.
- Server
Entry - A server entry for the
OpenAPIserversblock. - Streaming
Op - A streaming operation:
(HTTP method, path). - Transform
Config - Individual transform on/off switches (all default to
true).
Enums§
- Error
- Errors produced by
tonic-rest-openapilibrary operations.
Constants§
- DEFAULT_
ERROR_ SCHEMA_ REF - Default
$refpath for the REST error response schema.
Functions§
- discover
- Parse proto descriptor bytes and extract all RPC metadata.
- patch
- Apply the configured transform pipeline to an
OpenAPIYAML spec.
Type Aliases§
- Result
- Convenience alias used throughout the library’s public API.