utoipa

Derive Macro OpenApi

source
#[derive(OpenApi)]
{
    // Attributes available to this derive:
    #[openapi]
}
Expand description

Generate OpenApi base object with defaults from project settings.

This is #[derive] implementation for OpenApi trait. The macro accepts one openapi argument.

§OpenApi #[openapi(...)] attributes

  • paths(...) List of method references having attribute #[utoipa::path] macro.
  • components(schemas(...), responses(...)) Takes available component configurations. Currently only schema and response components are supported.
    • schemas(...) List of ToSchemas in OpenAPI schema.
    • responses(...) List of types that implement ToResponse.
  • modifiers(...) List of items implementing Modify trait for runtime OpenApi modification. See the trait documentation for more details.
  • security(...) List of SecurityRequirements global to all operations. See more details in #[utoipa::path(...)] attribute macro security options.
  • tags(...) List of Tag which must match the tag path operation. By default the tag is derived from path given to handlers list or if undefined then crate is used by default. Alternatively the tag name can be given to path operation via #[utoipa::path(...)] macro. Tag can be used to define extra information for the api to produce richer documentation.
  • external_docs(...) Can be used to reference external resource to the OpenAPI doc for extended documentation. External docs can be in OpenApi or in Tag level.
  • servers(...) Define servers as derive argument to the OpenApi. Servers are completely optional and thus can be omitted from the declaration.
  • info(...) Declare Info attribute values used to override the default values generated from Cargo environment variables. Note! Defined attributes will override the whole attribute from generated values of Cargo environment variables. E.g. defining contact(name = ...) will ultimately override whole contact of info and not just partially the name.

OpenApi derive macro will also derive Info for OpenApi specification using Cargo environment variables.

  • env CARGO_PKG_NAME map to info title
  • env CARGO_PKG_VERSION map to info version
  • env CARGO_PKG_DESCRIPTION map info description
  • env CARGO_PKG_AUTHORS map to contact name and email only first author will be used
  • env CARGO_PKG_LICENSE map to info license

§info(...) attribute syntax

  • title = ... Define title of the API. It can be literal string.
  • description = ... Define description of the API. Markdown can be used for rich text representation. It can be literal string or [include_str!] statement.
  • version = ... Override default version from Cargo.toml. Value must be literal string.
  • contact(...) Used to override the whole contact generated from environment variables.
    • name = ... Define identifying name of contact person / organization. It Can be a literal string.
    • email = ... Define email address of the contact person / organization. It can be a literal string.
    • url = ... Define URL pointing to the contact information. It must be in URL formatted string.
  • license(...) Used to override the whole license generated from environment variables.
    • name = ... License name of the API. It can be a literal string.
    • url = ... Define optional URL of the license. It must be URL formatted string.

§servers(...) attribute syntax

  • url = ... Define the url for server. It can be literal string.
  • description = ... Define description for the server. It can be literal string.
  • variables(...) Can be used to define variables for the url.
    • name = ... Is the first argument within parentheses. It must be literal string.
    • default = ... Defines a default value for the variable if nothing else will be provided. If enum_values is defined the default must be found within the enum options. It can be a literal string.
    • description = ... Define the description for the variable. It can be a literal string.
    • enum_values(...) Define list of possible values for the variable. Values must be literal strings.

Example server variable definition.

("username" = (default = "demo", description = "Default username for API")),
("port" = (enum_values("8080", "5000", "4545")))

§Examples

Define OpenApi schema with some paths and components.

#[derive(ToSchema)]
struct Pet {
    name: String,
    age: i32,
}

#[derive(ToSchema)]
enum Status {
    Active, InActive, Locked,
}

#[utoipa::path(get, path = "/pet")]
fn get_pet() -> Pet {
    Pet {
        name: "bob".to_string(),
        age: 8,
    }
}

#[utoipa::path(get, path = "/status")]
fn get_status() -> Status {
    Status::Active
}

#[derive(OpenApi)]
#[openapi(
    paths(get_pet, get_status),
    components(schemas(Pet, Status)),
    security(
        (),
        ("my_auth" = ["read:items", "edit:items"]),
        ("token_jwt" = [])
    ),
    tags(
        (name = "pets::api", description = "All about pets",
            external_docs(url = "http://more.about.pets.api", description = "Find out more"))
    ),
    external_docs(url = "http://more.about.our.apis", description = "More about our APIs")
)]
struct ApiDoc;

Define servers to OpenApi.

 #[derive(OpenApi)]
 #[openapi(
     servers(
         (url = "http://localhost:8989", description = "Local server"),
         (url = "http://api.{username}:{port}", description = "Remote API",
             variables(
                 ("username" = (default = "demo", description = "Default username for API")),
                 ("port" = (default = "8080", enum_values("8080", "5000", "3030"), description = "Supported ports for API"))
             )
         )
     )
 )]
 struct ApiDoc;

Define info attribute values used to override auto generated ones from Cargo environment variables.

#[derive(OpenApi)]
#[openapi(info(
    title = "title override",
    description = include_str!("./path/to/content"), // fail compile cause no such file
    contact(name = "Test")
))]
struct ApiDoc;

Create OpenAPI with reusable response.

#[derive(utoipa::ToSchema)]
struct Person {
    name: String,
}

/// Person list response
#[derive(utoipa::ToResponse)]
struct PersonList(Vec<Person>);

#[utoipa::path(
    get,
    path = "/person-list",
    responses(
        (status = 200, response = PersonList)
    )
)]
fn get_persons() -> Vec<Person> {
    vec![]
}

#[derive(utoipa::OpenApi)]
#[openapi(
    components(
        schemas(Person),
        responses(PersonList)
    )
)]
struct ApiDoc;