Skip to content

Commit

Permalink
Add implementation for utoipa-actix-web bindings
Browse files Browse the repository at this point in the history
Implements wrappers for `ServiceConfig`, `App`, `Scope` of actix-web.
This allows users to create `App` with collecting `paths` and `schemas`
recursively without registering them to `#[openapi(...)]` attribute.

Example of new supported syntax.
```rust
 use actix_web::{get, App};
 use utoipa_actix_web::{scope, AppExt};

 #[derive(utoipa::ToSchema)]
 struct User {
     id: i32,
 }

 #[utoipa::path(responses((status = OK, body = User)))]
 #[get("/user")]
 async fn get_user() -> Json<User> {
     Json(User { id: 1 })
 }

 let (_, mut api) = App::new()
     .into_utoipa_app()
     .service(scope::scope("/api/v1").service(get_user))
     .split_for_parts();
```

Relates #283 Relates #662
Closes #121 Closes #657
  • Loading branch information
juhaku committed Oct 22, 2024
1 parent 155657f commit 1efd7ed
Show file tree
Hide file tree
Showing 12 changed files with 1,095 additions and 9 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ members = [
"utoipa-scalar",
"utoipa-axum",
"utoipa-config",
"utoipa-actix-web",
]

[workspace.metadata.publish]
Expand All @@ -26,4 +27,5 @@ order = [
"utoipa-rapidoc",
"utoipa-scalar",
"utoipa-axum",
"utoipa-actix-web",
]
4 changes: 3 additions & 1 deletion scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set -e
: "${CARGO:=cargo}"
: "${CARGO_COMMAND:=test}"

crates="${1:-utoipa utoipa-gen utoipa-swagger-ui utoipa-redoc utoipa-rapidoc utoipa-scalar utoipa-axum}"
crates="${1:-utoipa utoipa-gen utoipa-swagger-ui utoipa-redoc utoipa-rapidoc utoipa-scalar utoipa-axum utoipa-config utoipa-actix-web}"

for crate in $crates; do
echo "Testing crate: $crate..."
Expand Down Expand Up @@ -44,5 +44,7 @@ for crate in $crates; do
pushd utoipa-config/config-test-crate/
$CARGO ${CARGO_COMMAND}
popd
elif [[ "$crate" == "utoipa-actix-web" ]]; then
$CARGO ${CARGO_COMMAND} -p utoipa-actix-web
fi
done
34 changes: 34 additions & 0 deletions utoipa-actix-web/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[package]
name = "utoipa-actix-web"
description = "Utoipa's actix-web bindings for seamless integration of the two"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
readme = "README.md"
keywords = ["utoipa", "actix-web", "bindings"]
repository = "https://github.com/juhaku/utoipa"
categories = ["web-programming"]
authors = ["Juha Kukkonen <[email protected]>"]
rust-version.workspace = true

[dependencies]
utoipa = { path = "../utoipa", version = "5" }
actix-web = { version = "4", default-features = false }
actix-service = "2"
once_cell = "1"

[dev-dependencies]
utoipa = { path = "../utoipa", version = "5", features = [
"actix_extras",
"macros",
"debug",
] }
actix-web = { version = "4", default-features = false, features = ["macros"] }
serde = "1"

[package.metadata.docs.rs]
features = []
rustdoc-args = ["--cfg", "doc_cfg"]

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(doc_cfg)'] }
1 change: 1 addition & 0 deletions utoipa-actix-web/LICENSE-APACHE
1 change: 1 addition & 0 deletions utoipa-actix-web/LICENSE-MIT
54 changes: 54 additions & 0 deletions utoipa-actix-web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# utoipa-actix-web - Bindings for Actix Web and utoipa

[![Utoipa build](https://github.com/juhaku/utoipa/actions/workflows/build.yaml/badge.svg)](https://github.com/juhaku/utoipa/actions/workflows/build.yaml)
[![crates.io](https://img.shields.io/crates/v/utoipa-actix-web.svg?label=crates.io&color=orange&logo=rust)](https://crates.io/crates/utoipa-actix-web)
[![docs.rs](https://img.shields.io/static/v1?label=docs.rs&message=utoipa-actix-web&color=blue&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K)](https://docs.rs/utoipa-actix-web/latest/)
![rustc](https://img.shields.io/static/v1?label=rustc&message=1.75&color=orange&logo=rust)

This crate implements necessary bindings for automatically collecting `paths` and `schemas` recursively from Actix Web
`App`, `Scope` and `ServiceConfig`. It provides natural API reducing duplication and support for scopes while generating
OpenAPI specification without the need to declare `paths` and `schemas` to `#[openapi(...)]` attribute of `OpenApi` derive.

Currently only `service(...)` calls supports automatic collection of schemas and paths. Manual routes via `route(...)` or
`Route::new().to(...)` is not supported.

## Install

Add dependency declaration to `Cargo.toml`.

```toml
[dependencies]
utoipa-actix-web = "0.1"
```

## Examples

Collect handlers annotated with `#[utoipa::path]` recursively from `service(...)` calls to compose OpenAPI spec.

```rust
use actix_web::{get, App};
use utoipa_actix_web::{scope, AppExt};

#[derive(utoipa::ToSchema)]
struct User {
id: i32,
}

#[utoipa::path(responses((status = OK, body = User)))]
#[get("/user")]
async fn get_user() -> Json<User> {
Json(User { id: 1 })
}

let (_, mut api) = App::new()
.into_utoipa_app()
.service(scope::scope("/api/v1").service(get_user))
.split_for_parts();
```

## License

Licensed under either of [Apache 2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT) license at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate
by you, shall be dual licensed, without any additional terms or conditions.
Loading

0 comments on commit 1efd7ed

Please sign in to comment.