All our services need to have a Swagger UI for presenting its current OpenAPI file to the user. Since our backend is completely built with Rust, hosting this Swagger UI is also done through a Rust process.
So to make the Swagger UI a first degree citizen in the Rust ecosystem, we decided to re-package the Swagger-UI as Rust module. This way, dependabot can pick up update to the underlying project und pull those dependencies into our projects.
This also has the benefit that whenever this dependency gets updates, we run our CI/CD pipeline to check whether the UI is still fine for us.
The Swagger UI is build packaged through github. So determining the current version is just another call against the Github API. This way we can decide whether update are in order or not. If a new version has been released, we download the minified JS and CSS files und update our local Rust repo with the new dependencies.
After those files were updated we also raise the module version to the same version as the github release. This way, the cargo version always matches the github version.
All the code required for this procedure in in the github action definition.
Using this crate is rather straight forward. The static resources are exposed as axum routes and can be merged with an existing rout definition. To implement those routes, you need to specify a prefix for the routes, as well as an API definition. The API definition can either be an inline YAML file or an external link to the API definition.
Here a sample of how to use the crate with an inline OpenAPI definition.
use axum::Router;
use swagger_ui_dist::{ApiDefinition, OpenApiSource};
#[tokio::main]
async fn main() {
let api_def = ApiDefinition {
uri_prefix: "/api",
api_definition: OpenApiSource::Inline(include_str!("petstore.yaml")),
title: Some("My Super Duper API"),
};
let app = Router::new().merge(swagger_ui_dist::generate_routes(api_def));
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
println!("listening on http://localhost:3000/api");
axum::serve(listener, app).await.unwrap();
}
crate.io link: https://crates.io/crates/swagger-ui-dist
github repo: https://github.com/apimeister/swagger-ui-dist-rs/