Skip to content

Commit

Permalink
Merge branch 'fix-rebase' into schemars-v1
Browse files Browse the repository at this point in the history
  • Loading branch information
rlebran committed Jul 11, 2024
2 parents 497d650 + 745a62b commit 8079e74
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 364 deletions.
33 changes: 16 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,24 +168,23 @@ For a complete example, see [the sample petstore](https://github.com/netwo-io/ap

### Feature flags

| name | description | extra dependencies |
|--------------------|--------------------------------------------------------------------------|-----------------------------------------------------------------|
| `query` (default) | Enables documenting `actix_web::web::Query` | |
| `actix` (default) | Enables documenting types from `actix` | |
| `lab_query` | Enables documenting `actix_web_lab::extract::Query` | [`actix-web-lab`](https://crates.io/crates/actix-web-lab) |
| `garde` | Enables input validation through `garde` | [`garde`](https://crates.io/crates/garde) |
| `actix-web-grants` | Enables support for `actix-web-grants` | [`actix-web-grants`](https://crates.io/crates/actix-web-grants) |
| `rapidoc` | Enables RapiDoc to expose the generated openapi file | |
| `redoc` | Enables Redoc to expose the generated openapi file | |
| `swagger-ui` | Enables Swagger UI to expose the generated openapi file | |
| `qs_query` | Enables documenting types from `serde_qs` | [`serde_qs`](https://crates.io/crates/serde-qs) |
| `chrono` | Enables documenting types from `chrono` | [`chrono`](https://crates.io/crates/chrono) |
| name | description | extra dependencies |
|-------------------|--------------------------------------------------------------------------|---------------------------------------------------------------|
| `query` (default) | Enables documenting `actix_web::web::Query` | |
| `actix` (default) | Enables documenting types from `actix` | |
| `lab_query` | Enables documenting `actix_web_lab::extract::Query` | [`actix-web-lab`](https://crates.io/crates/actix-web-lab) |
| `garde` | Enables input validation through `garde` | [`garde`](https://crates.io/crates/garde) |
| `rapidoc` | Enables RapiDoc to expose the generated openapi file | |
| `redoc` | Enables Redoc to expose the generated openapi file | |
| `swagger-ui` | Enables Swagger UI to expose the generated openapi file | |
| `qs_query` | Enables documenting types from `serde_qs` | [`serde_qs`](https://crates.io/crates/serde-qs) |
| `chrono` | Enables documenting types from `chrono` | [`chrono`](https://crates.io/crates/chrono) |
| `ipnetwork` | Enables documenting types from `ipnetwork` | [`ipnetwork`](https://crates.io/crates/ipnetwork) |
| `multipart` | Enables documenting types from `actix-multipart` | [`actix-multipart`](https://crates.io/crates/actix-multipart) |
| `rust_decimal` | Enables documenting types from `rust_decimal` | [`rust_decimal`](https://crates.io/crates/rust-decimal) |
| `uuid` | Enables documenting types from `uuid` | [`uuid`](https://crates.io/crates/uuid) |
| `url` | Enables documenting types from `url` | [`url`](https://crates.io/crates/url) |
| `extras` | Enables `chrono`, `multipart`, `rust_decimal`, `uuid` and `url` features | All from previous features |
| `multipart` | Enables documenting types from `actix-multipart` | [`actix-multipart`](https://crates.io/crates/actix-multipart) |
| `rust_decimal` | Enables documenting types from `rust_decimal` | [`rust_decimal`](https://crates.io/crates/rust-decimal) |
| `uuid` | Enables documenting types from `uuid` | [`uuid`](https://crates.io/crates/uuid) |
| `url` | Enables documenting types from `url` | [`url`](https://crates.io/crates/url) |
| `extras` | Enables `chrono`, `multipart`, `rust_decimal`, `uuid` and `url` features | All from previous features |

### What's next

Expand Down
124 changes: 2 additions & 122 deletions apistos-core/src/api_component.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
#[cfg(feature = "actix")]
use actix_web::Either;
use schemars::json_schema;
use serde_json::{json, Value};
use std::collections::BTreeMap;
#[cfg(feature = "actix")]
use std::future::Future;

use serde_json::{json, Value};

use apistos_models::paths::{MediaType, Parameter, RequestBody, Response, Responses};
use apistos_models::reference_or::ReferenceOr;
use apistos_models::security::SecurityScheme;
Expand Down Expand Up @@ -198,124 +196,6 @@ where
}
}

impl<T, E> ApiComponent for Either<T, E>
where
T: ApiComponent,
E: ApiComponent,
{
fn required() -> bool {
T::required() && E::required()
}

fn child_schemas(oas_version: OpenApiVersion) -> Vec<(String, ReferenceOr<ApistosSchema>)> {
let mut child_schemas = T::child_schemas(oas_version);
child_schemas.append(&mut E::child_schemas(oas_version));
child_schemas
}

fn raw_schema(oas_version: OpenApiVersion) -> Option<ReferenceOr<ApistosSchema>> {
match (T::raw_schema(oas_version), E::raw_schema(oas_version)) {
(Some(raw_schema1), Some(raw_schema2)) => {
let raw_schema1 = match raw_schema1 {
ReferenceOr::Object(schema_obj) => schema_obj.into_inner(),
ReferenceOr::Reference { _ref } => json_schema!({
"$ref": _ref
}),
};
let raw_schema2 = match raw_schema2 {
ReferenceOr::Object(schema_obj) => schema_obj.into_inner(),
ReferenceOr::Reference { _ref } => json_schema!({
"$ref": _ref
}),
};
let schema = Schema::try_from(json!({
"oneOf": [
raw_schema1,
raw_schema2
]
}))
.map_err(|err| {
log::warn!("Error generating json schema: {err:?}");
err
})
.map(|sch| ApistosSchema::new(sch, oas_version))
.unwrap_or_default()
.into();
Some(schema)
}
(Some(raw_schema1), None) => Some(raw_schema1),
(None, Some(raw_schema2)) => Some(raw_schema2),
(None, None) => None,
}
}

fn schema(oas_version: OpenApiVersion) -> Option<(String, ReferenceOr<ApistosSchema>)> {
match (T::schema(oas_version), E::schema(oas_version)) {
(Some(schema1), Some(schema2)) => {
let (schema_name1, schema1) = schema1;
let schema1 = match schema1 {
ReferenceOr::Object(schema_obj) => schema_obj.into_inner(),
ReferenceOr::Reference { _ref } => json_schema!({
"$ref": _ref
}),
};
let (schema_name2, schema2) = schema2;
let schema2 = match schema2 {
ReferenceOr::Object(schema_obj) => schema_obj.into_inner(),
ReferenceOr::Reference { _ref } => json_schema!({
"$ref": _ref
}),
};
let schema = Schema::try_from(json!({
"oneOf": [
schema1,
schema2
]
}))
.map_err(|err| {
log::warn!("Error generating json schema: {err:?}");
err
})
.map(|sch| ApistosSchema::new(sch, oas_version))
.unwrap_or_default()
.into();
let schema_name = format!("Either{}Or{}", schema_name1, schema_name2);
Some((schema_name, schema))
}
(Some(schema1), None) => Some(schema1),
(None, Some(schema2)) => Some(schema2),
(None, None) => None,
}
}

fn error_responses(oas_version: OpenApiVersion) -> Vec<(String, Response)> {
let mut error_responses = T::error_responses(oas_version);
error_responses.append(&mut E::error_responses(oas_version));
error_responses
}

fn error_schemas(oas_version: OpenApiVersion) -> BTreeMap<String, (String, ReferenceOr<ApistosSchema>)> {
let mut error_schemas = E::error_schemas(oas_version);
error_schemas.append(&mut T::error_schemas(oas_version));
error_schemas
}

fn responses(oas_version: OpenApiVersion, content_type: Option<String>) -> Option<Responses> {
let responses = T::responses(oas_version, content_type.clone());
match responses {
None => E::responses(oas_version, content_type),
Some(mut responses) => {
responses.responses.append(
&mut E::responses(oas_version, content_type)
.map(|r| r.responses)
.unwrap_or_default(),
);
Some(responses)
}
}
}
}

#[cfg(feature = "actix")]
impl<T> ApiComponent for actix_web::web::Data<T> {
fn child_schemas(_: OpenApiVersion) -> Vec<(String, ReferenceOr<ApistosSchema>)> {
Expand Down
2 changes: 0 additions & 2 deletions apistos-core/src/components/empty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ use actix_web::{HttpRequest, HttpResponse};
use apistos_models::reference_or::ReferenceOr;
use apistos_models::ApistosSchema;

use crate::ApiComponent;

macro_rules! empty_component_impl {
($($ty:ty),+) => {
$(impl ApiComponent for $ty {
Expand Down
102 changes: 0 additions & 102 deletions apistos-gen-test/src/tests/api_operation_oas_3_0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1461,105 +1461,3 @@ fn api_operation_root_vec() {
})
);
}

#[test]
fn api_operation_actix_web_grant() {
#[allow(clippy::unused_async)]
async fn extract(_req: &ServiceRequest) -> Result<HashSet<String>, Error> {
Ok(Default::default())
}

/// Add a new pet to the store
/// Add a new pet to the store
/// Plop
#[actix_web_grants::protect("ADMIN")]
#[api_operation(tag = "pet")]
pub(crate) async fn test(
_body: Json<test_models::Test>,
) -> Result<Json<Vec<test_models::TestResult>>, test_models::ErrorResponse> {
Ok(Json(vec![test_models::TestResult { id: 0 }]))
}

let components = __openapi_test::components(OpenApiVersion::OAS3_0);
// only one component here because: error does not have schema and Test is used both for query and response
assert_eq!(components.len(), 1);
let components = serde_json::to_value(components).expect("Unable to serialize as Json");

let operation = __openapi_test::operation(OpenApiVersion::OAS3_0);
let operation = serde_json::to_value(operation).expect("Unable to serialize as Json");

assert_json_eq!(
components,
json!([
{
"schemas": {
"Test": {
"properties": {
"test": {
"type": "string"
}
},
"required": [
"test"
],
"title": "Test",
"type": "object"
},
"TestResult": {
"properties": {
"id": {
"format": "uint32",
"minimum": 0,
"type": "integer"
}
},
"required": [
"id"
],
"title": "TestResult",
"type": "object"
}
}
}
])
);
assert_json_eq!(
operation,
json!({
"deprecated": false,
"description": "Add a new pet to the store\\\nPlop",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Test"
}
}
},
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TestResult"
}
}
}
},
"description": ""
},
"405": {
"description": "Invalid input"
}
},
"summary": "Add a new pet to the store",
"tags": [
"pet"
]
})
);
}
Loading

0 comments on commit 8079e74

Please sign in to comment.