Volga Open API Integration
OpenAPI 3.0 integration for the Volga web framework.
volga-open-api generates OpenAPI specifications directly from your routes, extractors and responders - without macros, codegen or runtime reflection.
It is fully optional and designed to stay out of your way.
Features
- OpenAPI 3.0 spec generation
- Multiple specs (e.g.
v1,v2) - Swagger UI integration
- Automatic schema inference
- Support for request/response examples
- Per-route and per-group metadata
- Zero required macros
- Zero runtime reflection
- Fully optional via feature flag
Philosophy
volga-open-api follows the same principles as Volga:
- No hidden magic
- No global registries
- No derive macros required
- No reflection
- Explicit > implicit
- Composable configuration
OpenAPI is generated from actual route definitions and extractor/response types.
If you don't expose the spec endpoints, nothing is publicly served.
Installation
Add the feature to your Cargo.toml:
= { = "...", = ["openapi"] }
Or use the standalone crate:
= "..."
Basic Usage
use App;
async
Spec will be available at:
/openapi.json
/openapi
Multiple Specs (API Versioning)
app.with_open_api
Bind routes to specific documents:
app.map_post
.open_api;
Routes default to the first spec unless explicitly assigned.
Groups
Route groups automatically inherit OpenAPI configuration:
app.group;
Group metadata merges with route-level metadata.
Request / Response Schema Generation
JSON
app.map_post
.open_api;
Form
app.map_put
.open_api;
Examples
app.map_post
.open_api;
Multipart / Streams / SSE
cfg.consumes_multipart;
cfg.produces_sse;
cfg.produces_stream;
Binary streams use:
type: string
format: binary
Automatic Schema Inference
For Deserialize types, schemas and examples are inferred automatically.
For Serialize-only types, response schema must be specified explicitly.
Types serde reads as a map
serde reads a struct with a #[serde(flatten)] field as a map, so that it can collect the keys the struct does not name for the flattened member - and a map does not say which keys it takes. None of such a struct's fields can be inferred, including the ones declared beside the flattened member: a request body is described as an object without properties (or as any value, when the struct sits inside it, as in a Vec), and query parameters are not described at all. Debug builds name each such input at startup. A struct that renames what it expects with #[serde(expecting = "..")] is not recognized as one, and is described as before.
Describe them by hand instead:
use OpenApiSchema;
let schema = object
.with_property
.with_property
.with_required;
app.map_post
.open_api;
app.map_get
.open_api;
Path parameters are named by the route template whatever the extractor describes; spell their types there - {id:integer}.
Routes naming one position differently
OpenAPI takes one templated path for one position, so routes that name a path parameter differently - GET /users/{id} beside POST /users/{name} - are described under one path in each document: named the way most of the routes described there are written, the first in alphabetical order on a tie. The other routes' path parameters are renamed to match. The wire does not notice, since a path parameter is read by position, but the handler reads its own name, so debug builds name each renamed route at startup. Naming the parameters alike describes every route under its own names.
Caching
Swagger UI is served with:
ETagCache-Controlstale-while-revalidate
Spec JSON endpoints are cache-friendly.
Security
OpenAPI endpoints are not exposed unless use_open_api() is called.
You can:
- Expose only JSON spec
- Serve UI behind auth
- Export spec without exposing endpoints
Roadmap
- Optional schema deduplication improvements
- Better enum support
- Component reuse optimizations
- Optional Redoc support
- Optional spec export to file
Why Not Macros?
volga-open-api intentionally avoids:
#[derive(OpenApi)]- Proc macros
- Reflection
- Code generation
Schemas are built using real serde behavior and actual route definitions.
License
Volga is licensed under the MIT License. Contributions welcome!