{"id":15178940,"url":"https://github.com/revoltchat/okapi","last_synced_at":"2025-10-01T20:32:06.871Z","repository":{"id":65346161,"uuid":"470676362","full_name":"revoltchat/okapi","owner":"revoltchat","description":"OpenAPI (AKA Swagger) document generation for Rust projects","archived":false,"fork":true,"pushed_at":"2024-10-20T22:31:21.000Z","size":1584,"stargazers_count":0,"open_issues_count":0,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-11-14T17:09:04.605Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"GREsau/okapi","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/revoltchat.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"ko_fi":"insertish","custom":"https://insrt.uk/donate"}},"created_at":"2022-03-16T17:00:11.000Z","updated_at":"2024-10-20T22:31:24.000Z","dependencies_parsed_at":"2023-02-10T15:45:43.041Z","dependency_job_id":null,"html_url":"https://github.com/revoltchat/okapi","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/revoltchat%2Fokapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/revoltchat%2Fokapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/revoltchat%2Fokapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/revoltchat%2Fokapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/revoltchat","download_url":"https://codeload.github.com/revoltchat/okapi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234897368,"owners_count":18903646,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-09-27T15:42:29.955Z","updated_at":"2025-10-01T20:32:01.384Z","avatar_url":"https://github.com/revoltchat.png","language":"Rust","funding_links":["https://ko-fi.com/insertish","https://insrt.uk/donate"],"categories":[],"sub_categories":[],"readme":"# Okapi\n\nOkapi: [![Download](https://img.shields.io/crates/v/okapi)](https://crates.io/crates/okapi/)\n[![API Docs](https://img.shields.io/badge/docs-okapi-blue)](https://docs.rs/okapi/latest/okapi/)\n\nRocket-Okapi: [![Download](https://img.shields.io/crates/v/rocket_okapi)](https://crates.io/crates/rocket_okapi)\n[![API Docs](https://img.shields.io/badge/docs-rocket_okapi-blue)](https://docs.rs/rocket_okapi/latest/rocket_okapi/)\n\n[![unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)\n\nAutomated OpenAPI (AKA Swagger) document generation for Rust/Rocket projects.\n\nNever have outdated documentation again.\nOkapi will generate documentation for you while setting up the server.\nIt uses a combination of [Rust Doc comments](https://doc.rust-lang.org/reference/comments.html#doc-comments)\nand programming logic to document your API.\n\nThe generated [OpenAPI][openapi_3.0.0] files can then be used by various programs to\nvisualize the documentation. Rocket-okapi currently includes [RapiDoc][rapidoc] and\n[Swagger UI][swagger_ui], but others can be used too.\n\nSupported OpenAPI Spec: [3.0.0][openapi_3.0.0]\u003cbr/\u003e\nSupported Rocket version (for `rocket_okapi`): [0.5.0-rc.1](https://crates.io/crates/rocket/0.5.0-rc.1)\n\nExample of generated documentation using Okapi:\n\n- DF Storyteller: [RapiDoc](https://docs.dfstoryteller.com/rapidoc/),\n  [Swagger UI](https://docs.dfstoryteller.com/swagger-ui/)\n- ...[^1]\n\n[^1]: More examples will be added, please open an issue if you have a good example.\n\n## Basic Usage\n\n```rust\nuse rocket::{get, post, serde::json::Json};\nuse revolt_rocket_okapi::{openapi, openapi_get_routes, swagger_ui::*};\nuse serde::{Deserialize, Serialize};\nuse schemars::JsonSchema;\n\n// Derive JsonSchema for and request/response models\n#[derive(Serialize, Deserialize, JsonSchema)]\n#[serde(rename_all = \"camelCase\")]\nstruct User {\n    user_id: u64,\n    username: String,\n    #[serde(default)]\n    email: Option\u003cString\u003e,\n}\n\n// Add #[openapi] attribute to your routes\n#[openapi]\n#[get(\"/user/\u003cid\u003e\")]\nfn get_user(id: u64) -\u003e Option\u003cJson\u003cUser\u003e\u003e {\n    Some(Json(User {\n        user_id: id,\n        username: \"bob\".to_owned(),\n        email: None,\n    }))\n}\n\n// You can tag your routes to group them together\n#[openapi(tag = \"Users\")]\n#[post(\"/user\", data = \"\u003cuser\u003e\")]\nfn create_user(user: Json\u003cUser\u003e) -\u003e Json\u003cUser\u003e {\n    user\n}\n\n// You can skip routes that you don't want to include in the openapi doc\n#[openapi(skip)]\n#[get(\"/hidden\")]\nfn hidden() -\u003e Json\u003c\u0026'static str\u003e {\n    Json(\"Hidden from swagger!\")\n}\n\npub fn make_rocket() -\u003e rocket::Rocket {\n    rocket::build()\n        // openapi_get_routes![...] will host the openapi document at `openapi.json`\n        .mount(\n            \"/\",\n            openapi_get_routes![get_user, create_user, hidden],\n        )\n        // You can optionally host swagger-ui too\n        .mount(\n            \"/swagger-ui/\",\n            make_swagger_ui(\u0026SwaggerUIConfig {\n                url: \"../openapi.json\".to_owned(),\n                ..Default::default()\n            }),\n        )\n}\n```\n\n## More examples\n\n- [Json web API](examples/json-web-api): Simple example showing the basics of Okapi.\n- [UUID](examples/uuid): Simple example showing basics, but using UUID's instead of\n  normal `u32`/`u64` id's.\n- [Custom Schema](examples/custom_schema): Shows how to add more/custom info to OpenAPI file\n  and merge multiple modules into one OpenAPI file.\n- [Secure Request Guard](examples/secure_request_guard): Shows how to implement authentication\n  methods into the OpenAPI file.\n  It shows: No authentication, API keys, HTTP Auth, OAuth2, OpenID and Cookies.\n- [Special types](examples/special-types): Showing use of some more obscure types and there usage.\n  (Still work in progress)\n\n## FAQ\n\n- **Q: Can I generate code from my OpenAPI file?**\u003cbr/\u003e\n  A: No, this crate only allows you to automatically generate the OpenAPI file from your code.\n  There are other crates that (attempt to) do this.\n  So:\n\n  - Rust code (Rocket) --\u003e OpenAPI == Okapi\n  - OpenAPI --\u003e Rust code != Okapi\n\n- **Q: My (diesel) database does not implement `OpenApiFromRequest`.**\u003cbr/\u003e\nA: This is because the parameter does not show up in the path, query or body.\nSo this is considered a [Request Guard](https://rocket.rs/v0.5-rc/guide/requests/#request-guards).\nThere is a [derive macro](https://github.com/GREsau/okapi/blob/master/examples/secure_request_guard/src/no_auth.rs)\nfor this, but this does not work in combination with the `#[database(\"...\")]` marco.\nYou can solve this my implementing it manually, like this:\n\u003cdetails\u003e\n    \u003csummary\u003eImplement `OpenApiFromRequest` for Diesel DB\u003c/summary\u003e\n\n```rust\nuse revolt_rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};\nuse revolt_rocket_okapi::gen::OpenApiGenerator;\nuse rocket_sync_db_pools::{diesel, database};\n\n#[database(\"sqlite_logs\")]\npub struct MyDB;\n\nimpl\u003c'r\u003e OpenApiFromRequest\u003c'r\u003e for MyDB {\n    fn from_request_input(\n        _gen: \u0026mut OpenApiGenerator,\n        _name: String,\n        _required: bool,\n    ) -\u003e revolt_rocket_okapi::Result\u003cRequestHeaderInput\u003e {\n        Ok(RequestHeaderInput::None)\n    }\n}\n```\n\n\u003c/details\u003e\n\n- **Q: ... does not implement `JsonSchema`?**\u003cbr/\u003e\n  A: The [`JsonSchema`](https://docs.rs/schemars/latest/schemars/trait.JsonSchema.html) implementation\n  is handled by [`Schemars`][schemars], make sure you enabled the right\n  [feature flags](https://github.com/GREsau/schemars#optional-dependencies) for it.\n  If it is still not implemented open an issue in the `Schemars` repo.\n\n- **Q: Can I add custom data to my OpenAPI spec?**\u003cbr/\u003e\n  A: Yes, see the [Custom Schema](examples/custom_schema) example. Okapi also has build in functions\n  if you want to merge the [`OpenAPI`](https://docs.rs/okapi/latest/okapi/openapi3/struct.OpenApi.html)\n  objects manually.\n\n- **Q: Can I use this with other web frameworks then Rocket?**\u003cbr/\u003e\n  A: Yes, but not there are no other implementations right now. But you can use the `Okapi` crate\n  independently and use Serde to create the json or yaml file.\n\n## Feature Flags\n\nOkapi:\n\n- `impl_json_schema`: Implements [`JsonSchema`](https://docs.rs/schemars/latest/schemars/trait.JsonSchema.html)\n  for [`Schemars`][schemars] and `Okapi` types themselves.\n- `preserve_order`: Keep the order of struct fields in `Schema` and all parts of the\n  `OpenAPI` documentation.\n\nRocket-Okapi:\n\n- `preserve_order`: Keep the order of struct fields in `Schema` and all parts of the\n  `OpenAPI` documentation.\n- `swagger`: Enable [Swagger UI][swagger_ui] for rendering documentation.\n- `rapidoc`: Enable [RapiDoc][rapidoc] for rendering documentation.\n- `uuid`: Enable UUID support in Rocket and Schemars.\n- `msgpack`: Enable [msgpack support for Rocket](https://docs.rs/rocket/0.5.0-rc.1/rocket/serde/msgpack/struct.MsgPack.html).\n  (when same Rocket feature flag is used.)\n- `secrets`: Enable [secrets support for Rocket](https://rocket.rs/v0.5-rc/guide/requests/#secret-key).\n  (when same Rocket feature flag is used.)\n\nNote that not all feature flags from [`Schemars`][schemars] are re-exported or enabled.\nSo if you have objects for which the `JsonSchema` trait is not implemented,\nyou might need to enable a [feature flag in `Schemars`](https://github.com/GREsau/schemars#optional-dependencies).\nFor an example see [the \"uuid\" example](examples/uuid/Cargo.toml). (Make sure crate versions match)\n\n## How it works\n\nThis crate automatically generates an OpenAPI file when the Rocket server starts.\nThe way this is done is shortly described here.\n\nThe [`Schemars`][schemars] crate provides us with the schemas for all the different\nstructures and enums. Okapi does not implement any schemas directly, this is all handled by `Schemars`.\n\nThe `Okapi` crate just contains all the structures needed to create an OpenAPI file.\nThis crate does not contain any code for the creation of them, just the structure and code to merge\ntwo [`OpenAPI`](https://docs.rs/okapi/latest/okapi/openapi3/struct.OpenApi.html) structured together.\nThis crate can be reused to create OpenAPI support in other web framework.\n\n`Rocket-Okapi` crate contains all the code for generating the OpenAPI file and serve it once created.\nThis code is usually executed using macro's like: [`mount_endpoints_and_merged_docs!{...}`,\n`openapi_get_routes![...]`, `openapi_get_routes_spec![...]` and `openapi_get_spec![...]`\n](https://docs.rs/rocket_okapi/latest/rocket_okapi/#macros).\n\nWhen the Rocket server is started (or wherever macro is placed) the OpenAPI file is generated once.\nThis file/structure is then stored in memory and will be served when requested.\n\nThe `Rocket-Okapi-codegen` crate contains code for\n[derive macros](https://doc.rust-lang.org/book/ch19-06-macros.html).\n`#[openapi]`, `rocket_okapi::openapi_spec![...]`, `rocket_okapi::openapi_routes![...]`\nand `#[derive(OpenApiFromRequest)]` in our case.\nThis needs to be in a separate crate because of Rust restrictions.\nNote: `derive` or `codegen` crates are usually a bit hard to work with then other crates.\nSo it is recommended to get some experience with how derive macros work before you\nchange things in here.\n\n## TODO\n\n- [ ] Tests\n- [ ] Documentation\n- [ ] Benchmark/optimise memory usage and allocations\n  - Note to self: https://crates.io/crates/graphannis-malloc_size_of looks useful\n- [x] Implement `OpenApiFrom___`/`OpenApiResponder` for more rocket/rocket-contrib types\n- [x] Allow customizing openapi generation settings, e.g.\n  - [x] custom json schema generation settings\n  - [x] change path the document is hosted at\n\n## License\n\nThis project is licensed under the [MIT license](LICENSE).\n\nAll contributions to this project will be similarly licensed.\n\n[schemars]: https://github.com/GREsau/schemars\n[openapi_3.0.0]: https://spec.openapis.org/oas/v3.0.0\n[rapidoc]: https://mrin9.github.io/RapiDoc/\n[swagger_ui]: https://swagger.io/tools/swagger-ui/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frevoltchat%2Fokapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frevoltchat%2Fokapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frevoltchat%2Fokapi/lists"}