gresau/okapi

Automated OpenAPI (AKA Swagger) document generation for Rust/Rocket projects

Never have outdated documentation again

okapi

okapi:

rocket-okapi:

.

. Okapi will generate documentation for you at compile time. It uses a combination of Rust Doc comments and programming logic to document your API.

The generated OpenAPI files can then be used to in by various programs to visualize the documentation. Rocket-okapi currently includes RapiDoc and Swagger UI, but others can be used too.

Supported OpenAPI Spec: 3.0.0

Example of generated documentation using okapi:

  • DF Storyteller: RapiDoc, Swagger UI
  • ...[^1]

[^1]: More examples will be added, please open an issue if you have a good example.

Basic Usage

#[macro_use]
extern crate rocket;
#[macro_use]
extern crate rocket_okapi;

use rocket_contrib::json::Json;
use rocket_okapi::swagger_ui::make_swagger_ui;
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;

// Derive JsonSchema for and request/response models
#[derive(Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
struct User {
    user_id: u64,
    username: String,
    #[serde(default)]
    email: Option<String>,
}

// Add #[openapi] attribute to your routes
#[openapi]
#[get("/user/<id>")]
fn get_user(id: u64) -> Option<Json<User>> {
    Some(Json(User {
        user_id: id,
        username: "bob".to_owned(),
        email: None,
    }))
}

// You can tag your routes to group them together
#[openapi(tag = "Users")]
#[post("/user", data = "<user>")]
fn create_user(user: Json<User>) -> Json<User> {
    user
}

// You can skip routes that you don't want to include in the openapi doc
#[openapi(skip)]
#[get("/hidden")]
fn hidden() -> Json<&'static str> {
    Json("Hidden from swagger!")
}

pub fn make_rocket() -> rocket::Rocket {
    rocket::build()
        // routes_with_openapi![...] will host the openapi document at openapi.json
        .mount(
            "/",
            routes_with_openapi![get_user, hidden],
        )
        // You can optionally host swagger-ui too
        .mount(
            "/swagger-ui/",
            make_swagger_ui(&SwaggerUIConfig {
                url: "../openapi.json".to_owned(),
                ..Default::default()
            }),
        )
}

TODO

  • Tests
  • Documentation
  • Benchmark/optimise memory usage and allocations
    • Note to self: https://crates.io/crates/graphannis-malloc_size_of looks useful
  • Implement OpenApiFrom___/OpenApiResponder for more rocket/rocket-contrib types
  • Allow customizing openapi generation settings, e.g.
    • custom json schema generation settings
    • change path the document is hosted at

License

This project is licensed under the MIT license.

All contributions to this project will be similarly licensed.

Issues

Collection of the latest Issues

twitchax

twitchax

Comment Icon0
image

Basically what the title says. 😄

If I change to #[openapi(skip)], it works just fine, so I think there is some problem occurring with how the attribute generates code. The error message is

So, it seems like the attribute may be stripping the named lifetime argument from the method definition.

antondc

antondc

Comment Icon0

I have a working example with one route and custom schema:

I am looking for a way to add paths into my schema, so I don't necessarily depend on the structs provided by the app. Cant see the way, and there are no examples in the library: any help will be welcome.

sebboer

sebboer

Comment Icon0

How can I implement the JsonSchema trait for an external struct? My endpoint returns an external struct that implements Serialize. But for this I can't run the derive macro for JsonSchema. I managed it with a wrapper struct and a manual implementation but it is very cumbersome. Is there a simpler approach to this?

barvirm

barvirm

Comment Icon1

Is it possible to create a tag description with the current API?

jimmybrenes

jimmybrenes

Comment Icon1

Hello,

I would like to know how to use the error.rs of the custom schema, specifically the function of the implementations

*impl std::fmt::Display for Error impl<'r> Responder<'r, 'static> for Error impl From<rocket::serde::json::Error<'_>> for Error

Also, I want to know if it is possible to choose which errors each endpoint returns, because as I have it now, the errors are shown for all the endpoints.

Thanks!

lrodriguez14

lrodriguez14

Comment Icon1

Hello,

I want to know if there is any way to add a description to the route parameters?

For example:

How can I add a little description for ? As we can see in the image the description is empty image

Thanks!

Flowneee

Flowneee

Comment Icon0

Hi. There is problem with deserializing and then serializing security scheme into JSON. I have a code which parse spec from YAML, then attempt to serialize it into both YAML and JSON. YAML is valid, but JSON produces duplicated fields type and scheme:

Problem is that fields type and scheme ends up in both data and extensions fields. Since it looks like some serde limitation/bug, proper solution could be custom deserialization. If this approach is OK, I could try to implement it.

I believe this might be related to https://github.com/GREsau/okapi/issues/74.

Debug output

JSON output (invalid)

YAML output (ok)

TaeyoonKwon

TaeyoonKwon

Comment Icon4

I am quite new to rust and found that default parameter is not allowed in rust.

but I could not find a way to set a default value for a parameter in the swagger documentation page.

How can I set the default value for like page = 1 in such codes?

snaggen

snaggen

Comment Icon0

When i generate rustdoc for my project, I find okapi_add_operation_for_ functions in the documentation, which is a bit confusing since these are not visible in the project source anywhere (since I assume they are derived from the okapi macros). I assume it would be good if these functions could be generated with #[doc(hidden)] somehow...

andrieshiemstra

andrieshiemstra

Comment Icon2

When deserializing from json the schemas from a param also get added to the extensions object of a param, resulting in faulty json being outputted when serializing again (schema attribute is added twice)

results in

The same happens when deserializing an operation with responses, deserializing and serializing this

results in this

snaggen

snaggen

enhancement
Comment Icon3

I have an api with a parameter async. This is a reserved word, so to handle this I have the following form defined, with the form field statement specifying that the variable is_async is called "async" in the API.

in the swagger UI this is still shown as is_async.

kov

kov

documentation
Comment Icon6

Hello! I am new to Rust and have recently learned about okapi. I am trying to use it for a REST API with a mongodb backend. I would like to properly handle and report mongodb-related failures as a HTTP 500 error, but I cannot figure out how to do that. I suppose I could implement OpenApiResponder for the mongodb errors, but it is not clear to me how to properly implement or how I would set up the return type for my handler. An example or more documentation would be very helpful =)

leeola

leeola

Comment Icon3

When two routes have the same name for a Request / Response the namespaces are clobbered. Example:

https://github.com/leeola/example_okapi_name_collision (specifically this file) will incorrectly report that the /two route has a response type of:

Instead of what it should be,

I'm happy to help developing a solution to this, but I'm unsure how best it can be handled. Ideally, I imagine something resembling idiomatic OpenAPI specs should be generated. Though, looking at the classic PetStore example it looks like that entire bottom area is ripe for having many structure names occupy the same namespace.

Thoughts on how best to handle this?

ThouCheese

ThouCheese

Comment Icon15

Thank you for this project! I've been struggling with documenting an API I build, and keeping that documentation up to date. I'm trying to add okapi to my project to have the documentation be created automatically. Unfortunately, I'm running into some issues:

As it stands, Rocket is able to provide neat Rust error messages. Consider the following example:

This fails with a compile error:

However, when the code is changed to use Okapi:

The error message changes:

The useful information about what caused the compilation error is gone, making it really hard to debug. Is there any way to get it back?

keorn

keorn

bug
Comment Icon0

When attempting to specify two routes with the same path and method, but different accepted format (e.g. format = "application/json" vs format = "application/cbor") error message appears:

The reason is that currently only method and path are taken into account when adding a new routes, while format should be considered as well.

(Thanks a lot for a nice crate!)

Versions

Find the latest versions by id

rocket-okapi-v0.8.0-rc.1 - Oct 10, 2021

Added

  • Added feature flag rapidoc to enable RapiDoc documentation viewer. (Based on #33)
  • Added RapiDoc v9.0.0
  • Forbid unsafe code in this crate. (#36)
  • Retrieve OpenApi object after generating. (#28)
  • Create mount_endpoints_and_merged_docs marco in order to streamline code structure for bigger projects. (#30)
  • Added new example for structuring bigger projects.
  • Allowed changing path where OpenApi file is hosted.
  • Added openapi_routes and openapi_spec macros to allow lower level access to the generation of the routes and specification respectively.
  • Added openapi_get_routes, openapi_get_routes_spec and openapi_get_spec to get a combination of Vec<rocket::Route> and/or okapi::openapi3::OpenApi.
  • Optionally allows the setting of OpenApiSettings when generating the OpenApi objects and Routes.
  • Add support for UUIDs, and added example. (#38, #46, #54)
  • Added log v0.4 as a dependency.
  • Added either v1 as a dependency. (Rocket dependency)
  • Added feature flag for msgpack (Re-exposing Rocket feature flag)
  • Added support for new Responder types (implemented OpenApiResponderInner):
    • std::fs::File
    • rocket::tokio::fs::File
    • std::borrow::Cow<'o, T>
    • either::Either<L, R>
    • std::io::Error
    • (rocket::http::ContentType, R)
    • (rocket::http::Status, R)
    • rocket::http::Status (#20)
    • rocket::response::status::NoContent
    • rocket::response::Redirect
    • rocket::response::content::Custom<T>
    • rocket::response::status::Conflict<T>
    • rocket::response::status::Custom<T>
    • rocket::response::Flash<R>
    • rocket::data::Capped<R>
    • rocket::response::Debug<E>
    • rocket::response::stream::ByteStream<S>
    • rocket::response::stream::ReaderStream<S>
    • rocket::response::stream::TextStream<S>
    • rocket::serde::msgpack::MsgPack<T> (only when feature msgpack is enabled)
  • Fully implement FromSegments for <param..> in path. (#41)
  • Implement OpenApiFromSegments for all that implement FromSegments and JsonSchema. (#41)
  • Implement OpenApiFromParam for all that implement FromParam and JsonSchema.
  • Implement OpenApiFromFormField for all that implement FromFormField and JsonSchema.
  • Added support for new FromData types (implemented OpenApiFromData):
    • String
    • &'r str
    • Cow<'r, str>
    • Vec<u8>
    • &'r [u8]
    • rocket::fs::TempFile<'r>
    • rocket::data::Capped<rocket::fs::TempFile<'r>>
    • rocket::data::Capped<Cow<'r, str>>
    • rocket::data::Capped<&'r str>
    • rocket::data::Capped<&'r rocket::http::RawStr>
    • rocket::data::Capped<&'r [u8]>
    • rocket::data::Capped<String>
    • rocket::data::Capped<Vec<u8>>
    • &'r rocket::http::RawStr
    • rocket::form::Form<T>
    • rocket::serde::msgpack::MsgPack<T> (only when feature msgpack is enabled)
  • Added feature flag for secrets (Re-exposing Rocket feature flag)
  • Added support for Request Guards and Security Scheme (aka Authentication and Authorization) (#47, #9, #8, #56)
  • Added support for new FromRequest types (implemented OpenApiFromRequest):
    • std::net::IpAddr
    • std::net::SocketAddr
    • Result<T, T::Error>
    • Option<T>
    • &'r rocket::config::Config
    • &'r rocket::config::SecretKey(only when feature secrets is enabled)
    • &'r rocket::data::Limits
    • &'r rocket::http::Accept
    • &'r rocket::http::ContentType
    • &'r rocket::http::CookieJar<'r>
    • &'r rocket::http::uri::Origin<'r>
    • &'r rocket::route::Route
    • rocket::http::Method
    • rocket::Shutdown
    • &'r rocket::State<T>
  • Added OpenApiFromRequest derive macro.
  • Added feature flag for preserve_order to keep the order of struct fields in Schema all parts of the OpenAPI documentation.
  • Okapi create is now re-exported and can be found as rocket_okapi::okapi.

Changed

  • Swagger UI is now only available under the feature swagger.
  • Updated Swagger UI to v3.52.0
  • The preserve_order feature flag is now enabled by default.
  • UrlObject has been moved from swagger_ui::UrlObject to settings::UrlObject.
  • Replaced manual implementations of OpenApiFromParam with generic version. So OpenApiFromParam is implemented for more types.
  • Replaced manual implementations of OpenApiFromFormField with generic version. So OpenApiFromFormField is implemented for more types.
  • Fixed setting of parameter location from "form" to "query".

Removed

  • Removed unused and unneeded files from Swagger UI to decrease file size.
  • routes_with_openapi has be removed and replaced with openapi_routes.

okapi-v0.7.0-rc.1 - Oct 10, 2021

Added

  • Forbid unsafe code in this crate. (#36)
  • Allow customization of OpenApi object.
  • Allow merging of OpenApi objects.
  • Added log v0.4 as a dependency.
  • Added map! macro for easy creation of okapi::Map objects.
  • Re-exported Schemars so the same version can be used without needing to import it.

Changed

  • Change OAuthFlows to better represent the different flows and allowed values within them.
  • Renamed derive_json_schema feature flag to impl_json_schema feature flag.

Fixed

  • Fixed casing in SecuritySchemeData.

rocket-okapi-v0.7.0-alpha-1 - Jun 12, 2021

Support for Rocket 0.5.0-rc1 (#42)!

rocket-okapi-v0.5.1 - May 25, 2020

Adds support for Query parameters in url (#26)

v0.5.0 - May 24, 2020

  • Add Cargo.toml info to openapi file (#23)
  • Add extra options to SwaggerUIConfig (#24)
  • Improve compile error/warning reporting (#12 / #27)

v0.4.0 - Mar 26, 2020

schemars updated to 0.7

v0.3.0 - Mar 26, 2020

schemars updated to 0.6

v0.2.0 - Dec 05, 2019

schemars updated to 0.5

Information - Updated May 06, 2022

Stars: 304
Forks: 46
Issues: 20

Repositories & Extras

serde-json for no_std programs

MIT license (LICENSE-MIT or

serde-json for no_std programs

macOS/iOS Security framework for Rust

MIT license (LICENSE-MIT or

macOS/iOS Security framework for Rust

OpenGliderNetwork client for Rust based on actix

MIT license (LICENSE-MIT or

OpenGliderNetwork client for Rust based on actix

A video game for programmers set in space

MIT license (LICENSE-MIT or

A video game for programmers set in space

Simple SQL migration manager for your project

MIT license (LICENSE-MIT or

Simple SQL migration manager for your project

TODO_README_DESCRIPTION

(LICENSE-MIT or Semantic Versioning 2

TODO_README_DESCRIPTION

CBOR Event library

MIT license (LICENSE-MIT or

CBOR Event library

Sqllogictest is a testing framework to verify the correctness of an SQL database

(LICENSE-MIT or Developer Certificate of Origin

Sqllogictest is a testing framework to verify the correctness of an SQL database

apply-license is a simple command-line tool that strives to make applying

open-source licenses to your software as easy and automated as possible

apply-license is a simple command-line tool that strives to make applying

Guerrilla (or Monkey) Patching in Rust for (unsafe) fun and profit

(LICENSE-MIT or monkey-patching-in-go

Guerrilla (or Monkey) Patching in Rust for (unsafe) fun and profit
Facebook Instagram Twitter GitHub Dribbble
Privacy