use axum::{Json, Router, routing::get};
use utoipa::openapi::OpenApi;
pub const SPEC_PATH: &str = "/openapi.json";
pub fn normalize(doc: &mut OpenApi) {
if let Some(license) = &doc.info.license {
if license.name.is_empty() {
doc.info.license = None;
}
}
}
pub fn spec_router(spec: OpenApi) -> Router {
spec_router_at(SPEC_PATH, spec)
}
pub fn spec_router_at(path: &str, spec: OpenApi) -> Router {
Router::new().route(
path,
get(move || {
let spec = spec.clone();
async move { Json(spec) }
}),
)
}
#[cfg(test)]
mod tests {
use super::*;
use axum::body::Body;
use http::{Request, StatusCode};
use http_body_util::BodyExt;
use tower::ServiceExt;
use utoipa::openapi::OpenApiBuilder;
#[tokio::test]
async fn serves_spec_as_json() {
let spec = OpenApiBuilder::new().build();
let app = spec_router(spec);
let resp = app
.oneshot(
Request::builder()
.uri("/openapi.json")
.body(Body::empty())
.unwrap(),
)
.await
.unwrap();
assert_eq!(resp.status(), StatusCode::OK);
let bytes = resp.into_body().collect().await.unwrap().to_bytes();
let value: serde_json::Value = serde_json::from_slice(&bytes).unwrap();
assert!(value.get("openapi").is_some(), "missing openapi version key");
}
}