Tutti i nostri servizi devono avere uno Swagger UI per presentare all’utente il relativo file OpenAPI corrente. Poiché il nostro backend è interamente sviluppato in Rust, anche l’hosting di questo Swagger UI avviene tramite un processo Rust.
Quindi, per rendere il Swagger UI un cittadino di primo grado nell’ecosistema Rust, abbiamo deciso di ripacchettare lo Swagger-UI come modulo Rust. In questo modo, dependabot può rilevare gli aggiornamenti del progetto sottostante e portare quelle dipendenze nei nostri progetti.
Questo ha anche il vantaggio che ogni volta che questa dipendenza viene aggiornata, eseguiamo la nostra pipeline CI/CD per verificare che l’interfaccia utente sia ancora corretta per noi.
Lo Swagger UI viene pacchettizzato tramite GitHub. Quindi determinare la versione corrente è solo un’altra chiamata contro l’API di GitHub. In questo modo possiamo decidere se sono necessari aggiornamenti o meno. Se viene rilasciata una nuova versione, scarichiamo i file JS e CSS minificati e aggiorniamo il nostro repository Rust locale con le nuove dipendenze.
Dopo che questi file sono stati aggiornati, aggiorniamo anche la versione del modulo alla stessa versione del rilascio su GitHub. In questo modo la versione su cargo corrisponde sempre alla versione su GitHub.
Tutto il codice necessario per questa procedura è nella definizione dell’azione GitHub.
Usare questo crate è piuttosto semplice. Le risorse statiche sono esposte come route di axum e possono essere unite a una definizione di route esistente. Per implementare queste route, è necessario specificare un prefisso per le route, oltre a una definizione dell’API. La definizione dell’API può essere un file YAML inline oppure un collegamento esterno alla definizione dell’API.
Ecco un esempio di come usare il crate con una definizione OpenAPI inline.
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();
}
Link su crates.io: https://crates.io/crates/swagger-ui-dist
Repo GitHub: https://github.com/apimeister/swagger-ui-dist-rs/