From d629865dc583e9587776262645741df3d348a2c9 Mon Sep 17 00:00:00 2001 From: Juha Kukkonen Date: Wed, 2 Oct 2024 11:12:52 +0300 Subject: [PATCH] Fix allow response `content_type` without schema Fix allow response with `content_type` without schema. ```rust #[utoipa::path(post, path = "/api/secret", responses( (status = OK, content_type = "application/octet-stream") ))] async fn post_secret() {} ``` Fixes #965 --- utoipa-gen/src/path/request_body.rs | 1 + utoipa-gen/src/path/response.rs | 4 +-- utoipa-gen/tests/path_response_derive_test.rs | 30 +++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/utoipa-gen/src/path/request_body.rs b/utoipa-gen/src/path/request_body.rs index 553aab72..971520f1 100644 --- a/utoipa-gen/src/path/request_body.rs +++ b/utoipa-gen/src/path/request_body.rs @@ -231,6 +231,7 @@ impl ToTokensDiagnostics for RequestBodyAttr<'_> { tokens.extend(quote! { utoipa::openapi::request_body::RequestBodyBuilder::new() }); + for (content_type, media_type, _) in media_types { let content_type_tokens = media_type .content_type diff --git a/utoipa-gen/src/path/response.rs b/utoipa-gen/src/path/response.rs index 655f2f9b..266fb5d0 100644 --- a/utoipa-gen/src/path/response.rs +++ b/utoipa-gen/src/path/response.rs @@ -419,9 +419,9 @@ impl ToTokensDiagnostics for ResponseTuple<'_> { tokens.extend(quote! { utoipa::openapi::ResponseBuilder::new().description(#description) }); - for media_type in value.content.iter().filter(|media_type| { - !matches!(media_type.schema, Schema::Default(DefaultSchema::None)) + !(matches!(media_type.schema, Schema::Default(DefaultSchema::None)) + && media_type.content_type.is_none()) }) { let default_content_type = media_type.schema.get_default_content_type()?; diff --git a/utoipa-gen/tests/path_response_derive_test.rs b/utoipa-gen/tests/path_response_derive_test.rs index d878b632..b77e7d1f 100644 --- a/utoipa-gen/tests/path_response_derive_test.rs +++ b/utoipa-gen/tests/path_response_derive_test.rs @@ -685,3 +685,33 @@ fn path_response_default_no_value_nor_ref() { }) ) } + +#[test] +fn path_response_with_no_schema() { + #![allow(unused)] + + /// Post some secret inner handler + #[utoipa::path(post, path = "/api/inner/secret", responses( + (status = OK, content_type = "application/octet-stream") + ))] + pub async fn post_secret() {} + + let operation = __path_post_secret::operation(); + let value = serde_json::to_value(operation).expect("operation is JSON serializable"); + + assert_json_eq!( + value, + json!({ + "operationId": "post_secret", + "responses": { + "200": { + "content": { + "application/octet-stream": {} + }, + "description": "" + } + }, + "summary": "Post some secret inner handler" + }) + ) +}