`.build()` Loading only the last component definitions
Closed this issue · 4 comments
I have an axtic-web API that is supposed to handle the uploading of files. The API has the following routes:
- GET
/ping
- Check to see if the service is available and also return the version - POST
/files/upload
- Upload a new file - GET
/files/{id}/stream
- Download a file - DELETE
/files/{id}
- Delete a file
The /ping
route looks something like this
#[derive(Serialize, ApiComponent, JsonSchema)]
enum Status {
Available,
}
#[derive(Serialize, ApiComponent, JsonSchema)]
struct PingResponse<'a> {
status: Status,
version: &'a str,
}
#[api_operation(
summary = "Route for applications to call to see if this service is available",
description = "Route for applications to call to see if this service is available",
produces = "application/json"
)]
pub async fn ping() -> Json<PingResponse<'static>> {
let version = match LOGGER.get() {
None => "Unknown",
Some(l) => match &l.config {
None => "Unknown",
Some(c) => &c.app_version,
},
};
return Json(PingResponse {
status: Status::Available,
version,
});
}
This is how i am building the app with apistos:
// ...
let app = app
.document(spec)
.service(resource("/ping").route(web::get().to(ping)))
.service(
scope("/files")
.service(resource("/upload").route(web::post().to(upload::<
FilesystemContext,
FilesystemContext,
ClientSession,
Auth,
FilesCollection,
UsersCollection,
Storage,
>)))
.service(resource("/{object_id}/stream").route(web::post().to(stream::<
FilesystemContext,
FilesystemContext,
ClientSession,
Auth,
FilesCollection,
Storage,
>)))
.service(resource("/{object_id}").route(web::delete().to(delete::<
FilesystemContext,
FilesystemContext,
ClientSession,
Auth,
FilesCollection,
FilesDatabase,
Storage,
>))),
)
.build("/spec");
// ...
When i now call the /spec
route to get the spec i only get the following schemas with the PingResponse not being included.
I already tried to group the two services in a new scope
with the path ""
which made the /spec
route unreachable
// ...
.service(
scope("")
.service(resource("/ping").route(web::get().to(ping)))
.service(
scope("/files")
.service(resource("/upload").route(web::post().to(upload::<
FilesystemContext,
FilesystemContext,
ClientSession,
Auth,
FilesCollection,
UsersCollection,
Storage,
>)))
.service(resource("/{object_id}/stream").route(web::post().to(stream::<
FilesystemContext,
FilesystemContext,
ClientSession,
Auth,
FilesCollection,
Storage,
>)))
.service(resource("/{object_id}").route(web::delete().to(delete::<
FilesystemContext,
FilesystemContext,
ClientSession,
Auth,
FilesCollection,
FilesDatabase,
Storage,
>))),
),
)
.build("/spec");
// ...
I also tried adding a /
to the top level scope and removing it from the children, but that also didn't work.
How can i have these two routes add their models to the component definitions?
Hi, I'm having a look.
Can second on having this issue.
I am using multiple .configure
s to setup the routes, and only definitions from the last .configure
get into the resulting openapi.json
Also, was able to pin down the likely source of the issue to update_from_def_holder function.
A quick and dirty patch to let mut components = definition_holder.components().into_iter().chain(open_api_spec.components.clone()).reduce(...)
results in the resulting definitions being fully defined
Same issue for me!
I have:
HttpServer::new(move || {
let cors = Cors::default()
.allowed_origin("http://localhost:8080")
.allowed_methods(vec!["GET", "POST"])
.allowed_headers(vec![
header::CONTENT_TYPE,
header::AUTHORIZATION,
header::ACCEPT,
])
.supports_credentials();
App::new()
.document(spec.clone())
.wrap(Logger::default())
.app_data(web::Data::new(AppState {
pool: pool.clone(),
config: config.clone(),
}))
.service(
scope("/v1/auth")
.service(resource("/signup").route(post().to(route::auth::signup)))
.service(resource("/login").route(post().to(route::auth::login_user)))
.service(resource("/logout").route(get().to(route::auth::logout_user))),
)
.service(
scope("/api/v1")
.service(
scope("/user")
.service(resource("/whoami").route(get().to(route::auth::who_am_i))),
)
.service(
scope("/scenario")
.service(
resource("/get_scenarios")
.route(get().to(route::scenario::get_scenarios)),
)
.service(
resource("/create_scenario")
.route(post().to(route::scenario::post_scenario)),
)
.service(
resource("/update_scenario")
.route(put().to(route::scenario::update_scenario)),
),
)
.service(
scope("/detection")
.service(
resource("/get_detections")
.route(get().to(route::detection::get_detections)),
)
.service(
resource("/create_detection")
.route(post().to(route::detection::post_detection)),
)
.service(
resource("/create_detections")
.route(post().to(route::detection::post_detections)),
)
.service(
resource("/update_detection")
.route(put().to(route::detection::put_detection)),
),
)
.service(
scope("/health").service(
resource("/check").route(get().to(route::health::health_check)),
),
),
)
.build_with(
"/v1/openapi.json",
BuildConfig::default()
.with(RapidocConfig::new(&"/v1/docs/rapidoc"))
.with(RedocConfig::new(&"/v1/docs/redoc"))
.with(ScalarConfig::new(&"/v1/docs/scalar"))
.with(SwaggerUIConfig::new(&"/v1/docs/swagger")),
)
.wrap(cors)
})
.bind(server_address)?
.run()
.await?;
So sorry about the long delay since this issue as been reported.
I spend more time than planned trying to include new things into v1.
A fix is on it's way and will be release tonight for v0.x.