OpenAPI with Aide
If the open-api
feature is enabled, an OpenAPI schema can be built for the app's Axum API by registering API routes
using Aide. The schema will then be generated and served at the
/api/_docs/api.json
route by default, and is also accessible via CLI commands or the
HttpService#open_api_schema
method.
Register routes
OpenAPI routes are registered with Aide's ApiRouter
,
which has a similar API to Axum's Router
.
const BASE: &str = "/api";
pub fn http_service(state: &AppContext) -> HttpServiceBuilder<AppContext> {
HttpServiceBuilder::new(Some(BASE), state)
// Create your routes as an `ApiRouter` in order to include it in the OpenAPI schema.
.api_router(
ApiRouter::new()
// Register a `GET` route on the `ApiRouter`
.api_route(
&build_path(BASE, "/example"),
get_with(example_get, example_get_docs),
),
)
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct ExampleResponse {}
#[instrument(skip_all)]
pub async fn example_get(
State(_state): State<AppContext>,
) -> RoadsterResult<Json<ExampleResponse>> {
Ok(Json(ExampleResponse {}))
}
pub fn example_get_docs(op: TransformOperation) -> TransformOperation {
op.description("Example API.")
.tag("Example")
.response_with::<200, Json<ExampleResponse>, _>(|res| res.example(ExampleResponse {}))
}
Get schema via API route
By default, the generated schema will be served at /api/_docs/api.json
. This route can be configured via the
service.http.default-routes.api-schema.route
config field.
# First, run your app
cargo run
# In a separate shell or browser, navigate to the API, e.g.
curl localhost:3000/api/_docs/api.json
Get schema via CLI
The schema can also be generated via a CLI command
cargo run -- roadster open-api -o $HOME/open-api.json
Get schema from the HttpService
The schema can also be generated programmatically using the HttpService
directly.
type App = RoadsterApp<AppContext>;
async fn open_api() -> RoadsterResult<()> {
// Build the app
let app: App = RoadsterApp::builder()
.state_provider(|context| Ok(context))
.add_service_provider(move |registry, state| {
Box::pin(async move {
registry
.register_builder(crate::http::http_service(state))
.await?;
Ok(())
})
})
.build();
// Prepare the app
let prepared = prepare(app, PrepareOptions::builder().build()).await?;
// Get the `HttpService`
let http_service = prepared.service_registry.get::<HttpService>()?;
// Get the OpenAPI schema
let schema = http_service.open_api_schema(&OpenApiArgs::builder().build())?;
println!("{schema}");
Ok(())
}