From 51d0f058ef2217a399a02882a33135c7b3337f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Ram=C3=ADrez?= Date: Thu, 20 Mar 2025 13:54:58 +0100 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Fix=20OpenAPI=20generation=20for?= =?UTF-8?q?=20header=20models=20with=20convert=5Funderscores?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastapi/openapi/utils.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/fastapi/openapi/utils.py b/fastapi/openapi/utils.py index bd8f3c106..e89198630 100644 --- a/fastapi/openapi/utils.py +++ b/fastapi/openapi/utils.py @@ -32,6 +32,7 @@ from fastapi.utils import ( generate_operation_id_for_path, is_body_allowed_for_status_code, ) +from pydantic import BaseModel from starlette.responses import JSONResponse from starlette.routing import BaseRoute from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY @@ -113,6 +114,13 @@ def _get_openapi_operation_parameters( (ParamTypes.header, header_params), (ParamTypes.cookie, cookie_params), ] + default_convert_underscores = True + if len(flat_dependant.header_params) == 1: + first_field = flat_dependant.header_params[0] + if lenient_issubclass(first_field.type_, BaseModel): + default_convert_underscores = getattr( + first_field.field_info, "convert_underscores", True + ) for param_type, param_group in parameter_groups: for param in param_group: field_info = param.field_info @@ -126,8 +134,16 @@ def _get_openapi_operation_parameters( field_mapping=field_mapping, separate_input_output_schemas=separate_input_output_schemas, ) + name = param.alias + if ( + param_type == ParamTypes.header + and param.alias == param.name + and default_convert_underscores + ): + name = param.name.replace("_", "-") + parameter = { - "name": param.alias, + "name": name, "in": param_type.value, "required": param.required, "schema": param_schema,