Skip to content

Commit

Permalink
Refactor OpenApiBuilder
Browse files Browse the repository at this point in the history
  • Loading branch information
Flowneee committed Dec 3, 2023
1 parent 13db160 commit b840e91
Show file tree
Hide file tree
Showing 14 changed files with 406 additions and 160 deletions.
23 changes: 7 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ macro `#[openapi]`.

## Example (with axum-integration feature).

```rust,compile
```rust,no_run
use axum::{extract::Query, Json};
use okapi_operation::{axum_integration::*, *};
use serde::Deserialize;
Expand Down Expand Up @@ -45,22 +45,13 @@ async fn echo_post(
}
fn main() {
// Here you can also add security schemes, other operations, modify internal OpenApi object.
let oas_builder = OpenApiBuilder::new("Demo", "1.0.0");
let app = Router::new()
.route("/echo/get", get(openapi_handler!(echo_get)))
.route("/echo/post", post(openapi_handler!(echo_post)))
.route_openapi_specification("/openapi", oas_builder)
.finish_openapi("/openapi", "Demo", "1.0.0")
.expect("no problem");
let fut = async {
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
};
//tokio::runtime::Runtime::new().block_on(fut);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app.into_make_service()).await.unwrap()
}
```

Expand All @@ -71,9 +62,9 @@ fn main() {
certain `axum` types):
* Compatibility with `axum`: since integration heavely rely on `axum` types, this crate will be compatible only with
few (maybe even one) last versions of `axum`;
* Currently supported `axum` versions: `0.6.x`.
* `axum-yaml`: enables ability to serve the spec in yaml format in case of present `Accept` header with `yaml` value.
Otherwise, in case of values `json|*/*` or empty, `json`'s being served.
* Currently supported `axum` versions: `0.7.x`.
* `yaml`: enables ability to serve the spec in yaml format in case of present `Accept` header with `yaml` value.
Otherwise, in case of values `json|*/*` or empty, `json`'s being served (currently affects only `axum-integration`).

## TODO

Expand Down
2 changes: 1 addition & 1 deletion okapi-examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ axum = "0.7"
axum-extra = { version = "0.9", features = ["typed-header"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }
okapi-operation = { path = "../okapi-operation", features = ["default", "yaml"] }
okapi-operation = { path = "../okapi-operation", features = ["default", "yaml", "axum-integration"] }
okapi-operation-macro = { path = "../okapi-operation-macro" }
5 changes: 1 addition & 4 deletions okapi-examples/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,10 @@ async fn echo_post(

#[tokio::main]
async fn main() {
// Here you can also add security schemes, other operations, modify internal OpenApi object.
let oas_builder = OpenApiBuilder::new("Demo", "1.0.0");

let app = Router::new()
.route("/echo/get", get(openapi_handler!(echo_get)))
.route("/echo/post", post(openapi_handler!(echo_post)))
.route_openapi_specification("/openapi", oas_builder)
.finish_openapi("/openapi", "Demo", "1.0.0")
.expect("no problem");

let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
Expand Down
29 changes: 26 additions & 3 deletions okapi-operation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,35 @@ All notable changes to this project will be documented in the changelog of the r
This project follows the [Semantic Versioning standard](https://semver.org/).


## [0.3.0 (Unreleased)] - 2023-12-03
## [0.3.0-rc1] - 2023-12-03
### Notable changes
- `axum` integration updated to be used with axum 0.7. Also this makes library unusable with older versions of `axum`.
- `axum` integration updated to be used with axum 0.7. Also this makes library unusable with older versions of `axum`;
- `OpenApiBuilder` rewritten, now providing more safe API to inner specification;
- Simplified usage of `axum-integration::Router` - it is now unnecessary to provide `OpenApiBuilder`.

### Added
- New methods for `OpenApiBuilder` for setting variuos fields in inner specification;
- `OpenApiBuilder::build()` method for building specification (replaced `generate_spec()`);
- `OpenApiBuilder` inside `axum-integration::Router`, which allow to omit explicit vreation of builder;
- New methods in `axum-integration::Router`:
- `set_openapi_builder_template` - replace `OpenApiBuilder` inside `Router`;
- `update_openapi_builder_template` - update `OpenApiBuilder` inside `Router`;
- `openapi_builder_template_mut` - get mutable reference to `OpenApiBuilder` from `Router`;
- `generate_openapi_builder` - generate `OpenApiBuilder` from `Router`;
- (!) `finish_openapi` - builder OpenAPI specification, mount it to path and return `axum::Router` (replaces `route_openapi_specification` method).

### Changed
- `axum` integration types updated to be used with axum 0.7.
- (breaking) `axum` integration types updated to be used with axum 0.7.

### Removed
- (breaking) `set_openapi_version`, because underlying library compatible only with OpenAPI `3.0.x` (`x` is 0 to 3, changes between versions minor). Now generated specification always have OpenAPI version `3.0.0`;
- (breaking) Bunch of old methods from `OpenApiBuilder`;
- (breaking) `axum-integration::Router::route_openapi_specification()` (replaced by `finish_openapi` method).

### Fixed
- (breaking) `OpenApiBuilder::add_operations` now use passed paths as is. Previously it converted it from `axum` format to OpenAPI, which could mess up integration with another framework. This change does not affect `axum` integration;
- (breaking) Feature `axum-integration` disabled by default, it was enabled by mistake previously;
- Minor documentation fixes.


## [0.2.2] - 2023-12-03
Expand Down
6 changes: 3 additions & 3 deletions okapi-operation/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "okapi-operation"
description = "Procedural macro for generating OpenAPI operation specification (using okapi)"
version = "0.3.0"
version = "0.3.0-rc1"
authors = ["Andrey Kononov [email protected]"]
edition = "2021"
license = "MIT"
Expand All @@ -28,11 +28,11 @@ serde_yaml = { version = "0.8", optional = true }
[dev-dependencies]
axum = "0.7"
axum-extra = { version = "0.9", features = ["typed-header"] }
tokio = "1"
tokio = { version = "1", features = ["full"] }
serde = { version = "1", features = ["derive"] }

[features]
default = ["macro", "axum-integration"]
default = ["macro"]

macro = ["okapi-operation-macro"]

Expand Down
53 changes: 42 additions & 11 deletions okapi-operation/docs/axum_integration.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Integration with axum

- [`Integration with axum`](#-integration-with-axum-)
* [Example](#example))
* [Customizing `OpenApiBuilder`](#customizing-openapibuilder)

This module provide integration with [`axum`] based on `#[openapi]` macro.

Integration is done by replacing [`axum::Router`] and [`axum::routing::MethodRouter`] with drop-in replacements, which support binding OpenAPI operation to handler using [`openapi_handler`] and [`openapi_service`] macros.
Expand All @@ -8,7 +12,7 @@ Integration is done by replacing [`axum::Router`] and [`axum::routing::MethodRou

This is example from root of this crate, but this time with [`axum_integration`].

```rust,compile
```no_run
use axum::{extract::Query, Json};
use okapi_operation::{axum_integration::*, *};
use serde::Deserialize;
Expand Down Expand Up @@ -43,21 +47,48 @@ async fn echo_post(
Json(body.0.data)
}
fn main() {
// Here you can also add security schemes, other operations, modify internal OpenApi object.
let oas_builder = OpenApiBuilder::new("Demo", "1.0.0");
#[tokio::main]
async fn main() {
let app = Router::new()
.route("/echo/get", get(openapi_handler!(echo_get)))
.route("/echo/post", post(openapi_handler!(echo_post)))
.route_openapi_specification("/openapi", oas_builder)
.finish_openapi("/openapi", "Demo", "1.0.0")
.expect("no problem");
let fut = async {
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app.into_make_service()).await.unwrap()
};
//tokio::runtime::Runtime::new().block_on(fut);
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app.into_make_service()).await.unwrap()
}
```

## Customizing [`OpenApiBuilder`]

By default [`Router`] have an empty [`OpenApiBuilder::default()`] inside, which is used as template when generating specification. The only 2 mandatory fields in specification is set when calling [`Router::finish_openapi`].

If you need to customize builder template, you can either:

* access existing builder with [`Router::openapi_builder_template_mut`] (example below) or [`Router::update_openapi_builder_template`];
* prepare your own builder and set it with [`Router::set_openapi_builder_template`].

```no_run
use axum::{extract::Query, Json};
use okapi_operation::{axum_integration::*, *};
use serde::Deserialize;
#[tokio::main]
async fn main() {
let mut app = Router::new();
// Setting description and ToS.
app.openapi_builder_template_mut()
.description("Some description")
.terms_of_service("Terms of Service");
// Proceed as usual.
let app = app
.finish_openapi("/openapi", "Demo", "1.0.0")
.expect("no problem");
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
axum::serve(listener, app.into_make_service()).await.unwrap()
}
```
Loading

0 comments on commit b840e91

Please sign in to comment.