Skip to content

Commit 700ccbd

Browse files
authored
Fix #137 (#140)
2 parents 48aeeac + c31a9b9 commit 700ccbd

File tree

2 files changed

+86
-11
lines changed

2 files changed

+86
-11
lines changed

apistos/src/app.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,12 +251,18 @@ where
251251
#[allow(clippy::unwrap_used)]
252252
fn update_from_def_holder<D: DefinitionHolder>(&mut self, definition_holder: &mut D) {
253253
let mut open_api_spec = self.open_api_spec.write().unwrap();
254-
let mut components = definition_holder.components().into_iter().reduce(|mut acc, component| {
255-
acc.schemas.extend(component.schemas);
256-
acc.responses.extend(component.responses);
257-
acc.security_schemes.extend(component.security_schemes);
258-
acc
259-
});
254+
let components = mem::take(&mut open_api_spec.components);
255+
256+
let mut components = definition_holder
257+
.components()
258+
.into_iter()
259+
.chain(components)
260+
.reduce(|mut acc, component| {
261+
acc.schemas.extend(component.schemas);
262+
acc.responses.extend(component.responses);
263+
acc.security_schemes.extend(component.security_schemes);
264+
acc
265+
});
260266
definition_holder.update_path_items(&mut open_api_spec.paths.paths);
261267
let mut paths = IndexMap::new();
262268
for (path, mut item) in mem::take(&mut open_api_spec.paths.paths) {

apistos/tests/routing.rs

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,16 @@ use actix_web::middleware::Logger;
22
use actix_web::web::{Json, Path};
33
use actix_web::{App, Error};
44

5+
use actix_web::test::{call_service, init_service, try_read_body_json, TestRequest};
56
use apistos::app::OpenApiWrapper;
67
use apistos::spec::Spec;
78
use apistos::web::{delete, get, patch, post, put, resource, scope, tagged_resource, tagged_scope, ServiceConfig};
8-
use apistos_gen::api_operation;
9+
use apistos_gen::{api_operation, ApiComponent};
910
use apistos_models::info::Info;
1011
use apistos_models::tag::Tag;
12+
use apistos_models::OpenApi;
13+
use schemars::JsonSchema;
14+
use serde::Serialize;
1115

1216
#[actix_web::test]
1317
async fn actix_routing() {
@@ -97,12 +101,79 @@ async fn actix_routing() {
97101
);
98102
}
99103

104+
#[actix_web::test]
105+
async fn actix_routing_multiple_root_definition_holder() {
106+
#[derive(ApiComponent, JsonSchema, Serialize)]
107+
pub(crate) struct TestResponse {
108+
pub(crate) value: String,
109+
}
110+
111+
#[derive(ApiComponent, JsonSchema, Serialize)]
112+
pub(crate) struct TestResponse2 {
113+
pub(crate) value: String,
114+
}
115+
116+
#[api_operation(tag = "pet")]
117+
pub(crate) async fn test(_params: Path<(u32, String)>) -> Result<Json<TestResponse>, Error> {
118+
Ok(Json(TestResponse {
119+
value: "plop".to_string(),
120+
}))
121+
}
122+
123+
#[api_operation(tag = "pet")]
124+
pub(crate) async fn test2(_params: Path<String>) -> Result<Json<TestResponse2>, Error> {
125+
Ok(Json(TestResponse2 {
126+
value: "plop".to_string(),
127+
}))
128+
}
129+
130+
let info = Info {
131+
title: "A well documented API".to_string(),
132+
description: Some("Really well document I mean it".to_string()),
133+
terms_of_service: Some("https://terms.com".to_string()),
134+
..Default::default()
135+
};
136+
let tags = vec![
137+
Tag {
138+
name: "pet".to_owned(),
139+
..Default::default()
140+
},
141+
Tag {
142+
name: "A super tag".to_owned(),
143+
..Default::default()
144+
},
145+
Tag {
146+
name: "Another super tag".to_owned(),
147+
..Default::default()
148+
},
149+
];
150+
let spec = Spec {
151+
info: info.clone(),
152+
tags: tags.clone(),
153+
..Default::default()
154+
};
155+
156+
let app = App::new()
157+
.document(spec)
158+
.service(scope("test").service(resource("/{plop_id}/{clap_name}").route(get().to(test))))
159+
.service(scope("test2").service(resource("/{clap_name}").route(get().to(test2))))
160+
.build("/openapi.json");
161+
let app = init_service(app).await;
162+
163+
let req = TestRequest::get().uri("/openapi.json").to_request();
164+
let resp = call_service(&app, req).await;
165+
assert!(resp.status().is_success());
166+
167+
let body: OpenApi = try_read_body_json(resp).await.expect("Unable to read body");
168+
let components = body.components.expect("Unable to get components");
169+
170+
assert_eq!(components.schemas.len(), 2);
171+
}
172+
100173
// Imports bellow aim at making clippy happy. Those dependencies are necessary for integration-test.
101174
use actix_service as _;
102-
use actix_web::test::{call_service, init_service, try_read_body_json, TestRequest};
103175
use actix_web_lab as _;
104176
use apistos_core as _;
105-
use apistos_models::OpenApi;
106177
use apistos_plugins as _;
107178
use apistos_rapidoc as _;
108179
use apistos_redoc as _;
@@ -115,6 +186,4 @@ use log as _;
115186
use md5 as _;
116187
use once_cell as _;
117188
use regex as _;
118-
use schemars as _;
119-
use serde as _;
120189
use serde_json as _;

0 commit comments

Comments
 (0)