axum-openapi3

Crates.ioaxum-openapi3
lib.rsaxum-openapi3
version0.1.0
sourcesrc
created_at2024-12-06 16:16:59.023621
updated_at2024-12-06 16:16:59.023621
descriptionFacilitate the generation of OpenAPI 3.0 documentation for axum applications.
homepagehttps://crates.io/crates/axum-openapi3
repositoryhttps://github.com/oramasearch/axum-openapi3
max_upload_size
id1474430
size54,010
Tommaso Allevi (allevo)

documentation

https://docs.rs/axum-openapi3

README

Axum OpenAPI 3

This is a library for generating OpenAPI 3.0 specifications from Axum applications.

This library uses utoipa crate to generate the OpenAPI spec from Rust types. See the utoipa crate for more information on how to use it.

Example

use std::net::{IpAddr, SocketAddr};

use axum::extract::{Path, Query};
use axum::response::IntoResponse;
use axum::Json;
use axum_openapi3::utoipa; // Needed for ToSchema and IntoParams derive
use axum_openapi3::utoipa::*; // Needed for ToSchema and IntoParams derive
use axum_openapi3::utoipa::openapi::{InfoBuilder, OpenApiBuilder};
use serde::{Deserialize, Serialize};

use axum_openapi3::{
    build_openapi, // function for building the openapi spec
    endpoint,      // macro for defining endpoints
    reset_openapi, // function for cleaning the openapi cache (mostly used for testing)
    AddRoute,      // `add` method for Router to add routes also to the openapi spec
};

#[derive(Serialize, Deserialize, ToSchema)]
struct Todo {
    id: u64,
    title: String,
    completed: bool,
}
#[derive(Serialize, Deserialize, IntoParams)]
struct TodoFilter {
    completed: bool,
}

#[endpoint(method = "POST", path = "/todos", description = "Insert a new todo")]
async fn insert_todo(_: Json<Todo>) -> Json<Todo> {
    unreachable!("")
}
#[endpoint(
    method = "PATCH",
    path = "/todos/:id/complete",
    description = "Mark a todo as completed"
)]
async fn mark_todo_as_complete(_: Path<u64>, _: Json<u64>) -> Json<Todo> {
    unreachable!("")
}
#[endpoint(
    method = "GET",
    path = "/todos/filter",
    description = "Filter todos by completed status"
)]
async fn filter(_: Query<TodoFilter>) -> Json<Vec<Todo>> {
    unreachable!("")
}

fn get_router() -> axum::Router {
    axum::Router::new()
        .add(insert_todo())
        .add(mark_todo_as_complete())
        .add(filter())
        .add(openapi())
}

#[endpoint(method = "GET", path = "/openapi.json", description = "OpenAPI spec")]
async fn openapi() -> impl IntoResponse {
    // `build_openapi` caches the openapi spec, so it's not necessary to call it every time
    let openapi = build_openapi(|| {
        OpenApiBuilder::new().info(InfoBuilder::new().title("My Webserver").version("0.1.0"))
    });

    Json(openapi)
}

#[tokio::main]
async fn main() {
    reset_openapi(); // clean the openapi cache. Mostly used for testing

    let ip: IpAddr = "127.0.0.1".parse().unwrap();
    let _addr = SocketAddr::new(ip, 8080);

    let _router = get_router();

    // De-comment the following lines to start the server

    // let listener = tokio::net::TcpListener::bind(addr)
    //     .await
    //     .expect("failed to bind address");
    // println!("Address binded. Starting web server on http://{}", addr);
    // axum::serve(listener, router).await.expect("server failed");
}

Limitations

  • No nested routes: axum allows nested routes, but this library does not support them: the endpoints must be defined at the root level of the router.

  • Only one http server per process: axum-openapi3 uses a global cache to store the OpenAPI spec, so it's not possible to have more than one http server per process.

  • Only Json responses: the library only supports Json responses. Other response types are not supported. The endpoint will be generated, but with empty response.

License

Licensed under Apache License, Version 2.0, (LICENSE)

Commit count: 12

cargo fmt