diff --git a/chaotic-openapi/chaotic_openapi/back/cpp_client/renderer.py b/chaotic-openapi/chaotic_openapi/back/cpp_client/renderer.py index 15c17cdf0df0..869bcd35a8e5 100644 --- a/chaotic-openapi/chaotic_openapi/back/cpp_client/renderer.py +++ b/chaotic-openapi/chaotic_openapi/back/cpp_client/renderer.py @@ -76,6 +76,7 @@ def make_env() -> jinja2.Environment: def render(spec: types.ClientSpec, context: Context) -> List[CppOutput]: env = { + 'spec': spec, 'namespace': spec.cpp_namespace, 'name': spec.client_name, 'base_url': 'http://example.com', # TODO diff --git a/chaotic-openapi/chaotic_openapi/back/cpp_client/templates/requests.cpp.jinja b/chaotic-openapi/chaotic_openapi/back/cpp_client/templates/requests.cpp.jinja index 27f0fdbd4a56..ebdc7d841337 100644 --- a/chaotic-openapi/chaotic_openapi/back/cpp_client/templates/requests.cpp.jinja +++ b/chaotic-openapi/chaotic_openapi/back/cpp_client/templates/requests.cpp.jinja @@ -32,8 +32,16 @@ void SerializeRequest(const Request& request, USERVER_NAMESPACE::clients::http:: // http_request.data(ToJsonString(request.body)); http_request.data(ToString(USERVER_NAMESPACE::formats::json::ValueBuilder(request.body).ExtractValue())); {% elif len(op.request_bodies) > 1 %} - {# TODO #} - {%- for body in op.request_bodies -%} + switch (request.body.index()) { + {%- for num, body in enumerate(op.request_bodies) -%} + case {{ num }}: + http_request.headers({kContentType, "{{ body.content_type }}"); + {% if body.content_type == 'application/json' %} + // http_request.data(ToJsonString(std::get<{{ num }}>(request.body))); + http_request.data(ToString(USERVER_NAMESPACE::formats::json::ValueBuilder(std::get<{{ num }}>(request.body)).ExtractValue())); + {% else %} + http_request.data(std::get<{{ num }}>(request.body).data); + {% endif %} {% endfor %} UASSERT(false); {% endif %} diff --git a/chaotic-openapi/chaotic_openapi/back/cpp_client/templates/requests.hpp.jinja b/chaotic-openapi/chaotic_openapi/back/cpp_client/templates/requests.hpp.jinja index 1a0a664d0882..e92f5fea9b4d 100644 --- a/chaotic-openapi/chaotic_openapi/back/cpp_client/templates/requests.hpp.jinja +++ b/chaotic-openapi/chaotic_openapi/back/cpp_client/templates/requests.hpp.jinja @@ -1,11 +1,15 @@ #pragma once #include -{# TODO: variant #} +{% if spec.has_multiple_content_type_request() %} +#include +{% endif %} #include +{% for include in spec.requests_declaration_includes() %} +#include <{{ include }}> +{% endfor %} -{# TODO: request_bodies includes #} namespace {{ namespace }} { @@ -16,9 +20,14 @@ namespace {{ namespace }} { {% if len(op.request_bodies) == 1 %} using Body = {{ op.request_bodies[0].schema.cpp_user_name() }}; {% elif len(op.request_bodies) > 1 %} + {%- for body in op.request_bodies -%} + struct {{ op.request_bodies[0].cpp_body_type() }} { + std::string data; + }; + {% endfor %} using Body = std::variant< {%- for body in op.request_bodies -%} - {{ op.request_bodies[0].schema.cpp_user_name() }} + {{ op.request_bodies[0].cpp_body_type() }} {%- if not loop.last %},{% endif %} {% endfor %} > diff --git a/chaotic-openapi/chaotic_openapi/back/cpp_client/types.py b/chaotic-openapi/chaotic_openapi/back/cpp_client/types.py index 5279cb2263ba..941de090cf50 100644 --- a/chaotic-openapi/chaotic_openapi/back/cpp_client/types.py +++ b/chaotic-openapi/chaotic_openapi/back/cpp_client/types.py @@ -13,16 +13,27 @@ class Parameter: cpp_type: str parser: str + def declaration_includes(self) -> str: + # TODO + return [] + @dataclasses.dataclass class RequestBody: content_type: str schema: Optional[cpp_types.CppType] + def cpp_body_type(self) -> str: + name = cpp_names.camel_case( + cpp_names.cpp_identifier(self.content_type), + ) + return f'Body{name}' + @dataclasses.dataclass class Response: status: int + # TODO def is_error(self) -> bool: return self.status >= 400 @@ -62,3 +73,20 @@ class ClientSpec: client_name: str cpp_namespace: str operations: List[Operation] + + def has_multiple_content_type_request(self) -> bool: + for op in self.operations: + if len(op.request_bodies) > 1: + return True + return False + + def requests_declaration_includes(self) -> List[str]: + includes = set() + for op in self.operations: + # TODO: for body in op.request_bodies: + # TODO: if body.schema: + # TODO: includes.update(body.schema.declaration_includes()) + for param in op.parameters: + includes.update(param.declaration_includes()) + + return list(includes)