diff --git a/poem-openapi-derive/src/api.rs b/poem-openapi-derive/src/api.rs index 2bef30819f..89f4e8430e 100644 --- a/poem-openapi-derive/src/api.rs +++ b/poem-openapi-derive/src/api.rs @@ -76,6 +76,7 @@ pub(crate) fn generate( }; let crate_name = get_crate_name(api_args.internal); let ident = item_impl.self_ty.clone(); + let (impl_generics, _, where_clause) = item_impl.generics.split_for_impl(); let mut ctx = Context { add_routes: Default::default(), operations: Default::default(), @@ -133,7 +134,7 @@ pub(crate) fn generate( let expanded = quote! { #item_impl - impl #crate_name::OpenApi for #ident { + impl #impl_generics #crate_name::OpenApi for #ident #where_clause { fn meta() -> ::std::vec::Vec<#crate_name::registry::MetaApi> { ::std::vec![#crate_name::registry::MetaApi { paths: ::std::vec![#(#paths),*], diff --git a/poem-openapi/CHANGELOG.md b/poem-openapi/CHANGELOG.md index e641827a01..fb68160afe 100644 --- a/poem-openapi/CHANGELOG.md +++ b/poem-openapi/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +# [1.3.10] 2022-3-7 + +- Add support generic for `OpenAPI` macro. [#216](https://github.com/poem-web/poem/issues/216) + # [1.3.9] 2022-3-7 - Add `skip_serializing_if_is_none`, `skip_serializing_if_is_empty` and `skip_serializing_if` attributes to `Object` macro. [#220](https://github.com/poem-web/poem/issues/220) diff --git a/poem-openapi/tests/api.rs b/poem-openapi/tests/api.rs index 57aa3008f8..ea5da2756a 100644 --- a/poem-openapi/tests/api.rs +++ b/poem-openapi/tests/api.rs @@ -617,3 +617,46 @@ async fn external_docs() { }) ); } + +#[tokio::test] +async fn generic() { + trait MyApiPort: Send + Sync + 'static { + fn test(&self) -> String; + } + + struct MyApiA; + + impl MyApiPort for MyApiA { + fn test(&self) -> String { + "test".to_string() + } + } + + struct MyOpenApi { + api: MyApi, + } + + #[OpenApi] + impl MyOpenApi { + #[oai(path = "/some_call", method = "get")] + async fn some_call(&self) -> Json { + Json(self.api.test()) + } + } + + let ep = OpenApiService::new(MyOpenApi { api: MyApiA }, "test", "1.0").into_endpoint(); + let resp = ep + .call( + poem::Request::builder() + .method(Method::GET) + .uri(Uri::from_static("/some_call")) + .finish(), + ) + .await + .unwrap(); + assert_eq!(resp.status(), StatusCode::OK); + assert_eq!( + resp.into_body().into_json::().await.unwrap(), + "test" + ); +}