From 9633e31c8dcdda8f041e2e018f6a7a5624adb293 Mon Sep 17 00:00:00 2001 From: Raphael SMADJA Date: Fri, 15 Mar 2024 17:22:49 +0100 Subject: [PATCH] feat: support all application/json-like content types --- src/OpenApiLibCore/openapi_libcore.py | 35 +++++++++++++------ .../suites/test_get_request_data.robot | 6 ++-- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/OpenApiLibCore/openapi_libcore.py b/src/OpenApiLibCore/openapi_libcore.py index 20ba3c4..bab053c 100644 --- a/src/OpenApiLibCore/openapi_libcore.py +++ b/src/OpenApiLibCore/openapi_libcore.py @@ -119,6 +119,7 @@ """ import json as _json +import re import sys from copy import deepcopy from dataclasses import Field, dataclass, field, make_dataclass @@ -849,6 +850,7 @@ def get_request_data(self, endpoint: str, method: str) -> RequestData: has_body=False, ) content_schema = resolve_schema(self.get_content_schema(body_spec)) + headers.update({"content-type": self.get_content_type(body_spec)}) dto_data = self.get_json_data_for_dto_class( schema=content_schema, dto_class=dto_class, @@ -916,19 +918,32 @@ def get_request_parameters( headers = self.get_parameter_data(header_params, parameter_relations) return parameters, params, headers - @staticmethod - def get_content_schema(body_spec: Dict[str, Any]) -> Dict[str, Any]: + @classmethod + def get_content_schema(cls, body_spec: Dict[str, Any]) -> Dict[str, Any]: """Get the content schema from the requestBody spec.""" - content_types = body_spec["content"].keys() - if "application/json" not in content_types: - # At present no supported for other types. - raise NotImplementedError( - f"Only content type 'application/json' is supported. " - f"Content types definded in the spec are '{content_types}'." - ) - content_schema = body_spec["content"]["application/json"]["schema"] + content_type = cls.get_content_type(body_spec) + content_schema = body_spec["content"][content_type]["schema"] return resolve_schema(content_schema) + @staticmethod + def get_content_type(body_spec: Dict[str, Any]) -> str: + """Get and validate the first supported content type from the requested body spec + + Should be application/json like content type, + e.g "application/json;charset=utf-8" or "application/merge-patch+json" + """ + content_types: List[str] = body_spec["content"].keys() + json_regex = r"application/([a-z\-]+\+)?json(;\s?charset=(.+))?" + for content_type in content_types: + if re.search(json_regex, content_type): + return content_type + + # At present no supported for other types. + raise NotImplementedError( + f"Only content types like 'application/json' are supported. " + f"Content types definded in the spec are '{content_types}'." + ) + def get_parametrized_endpoint(self, endpoint: str) -> str: """ Get the parametrized endpoint as found in the `paths` section of the openapi diff --git a/tests/libcore/suites/test_get_request_data.robot b/tests/libcore/suites/test_get_request_data.robot index a9cfb36..b018241 100644 --- a/tests/libcore/suites/test_get_request_data.robot +++ b/tests/libcore/suites/test_get_request_data.robot @@ -36,7 +36,8 @@ Test Get Request Data For Endpoint With RequestBody Should Not Be Empty ${request_data.dto_schema} Should Be Equal ${request_data.parameters} ${list} Should Be Equal ${request_data.params} ${dict} - Should Be Equal ${request_data.headers} ${dict} + &{expected_headers}= Create Dictionary content-type=application/json + Should Be Equal ${request_data.headers} ${expected_headers} Should Be True ${request_data.has_body} Test Get Request Data For Endpoint Without RequestBody But With DtoClass @@ -57,5 +58,6 @@ Test Get Request Data For Endpoint Without RequestBody But With DtoClass # Should Be Equal ${request_data.dto_schema} ${dict} # Should Not Be Empty ${request_data.parameters} # Should Be Equal ${request_data.params} ${dict} -# Should Be Equal ${request_data.headers} ${dict} +# &{expected_headers}= Create Dictionary content-type=application/json +# Should Be Equal ${request_data.headers} ${expected_headers} # Should Be True ${request_data.has_body}