diff --git a/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/chaotic_handlers_list.hpp.jinja b/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/chaotic_handlers_list.hpp.jinja index 8741774cb2b4..9a3ee9d920e9 100644 --- a/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/chaotic_handlers_list.hpp.jinja +++ b/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/chaotic_handlers_list.hpp.jinja @@ -18,8 +18,6 @@ namespace {{ spec.cpp_namespace }} { /// @endcode inline {{ userver }}::components::ComponentList ChaoticHandlersList() { return {{ userver }}::components::ComponentList() - .Append<{{ userver }}::components::Container< - {{ userver }}::chaotic::openapi::server::dependencies::Factories>>() {% for op in spec.operations %} .Append<{{ spec.cpp_namespace }}::{{ op.cpp_namespace() }}::Handler>() {% endfor %} diff --git a/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/view.cpp.jinja b/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/view.cpp.jinja index 799e79a5b343..bf3382af0ef3 100644 --- a/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/view.cpp.jinja +++ b/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/view.cpp.jinja @@ -2,7 +2,10 @@ namespace {{ spec.cpp_namespace }}::{{ op.cpp_namespace() }} { -Response View::Handle(Request&& /*request*/, Deps&& /*deps*/) { +Response View::Handle( + Request&& /*request*/, + Deps&& /*deps*/, + RequestContext& /*context*/) { // Handle request using dependencies from Deps (clients, caches, configs, databases...) return {}; } @@ -32,7 +35,7 @@ std::string View::GetRequestBodyForLogging(const std::string& body) { std::string View::GetResponseForLogging( const Response& response, const std::string& serialized_response, - {{ userver }}::server::request::RequestContext& context) { + RequestContext& context) { (void)response; (void)serialized_response; (void)context; diff --git a/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/view.hpp.jinja b/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/view.hpp.jinja index e3dee8e446d7..d09e92476b55 100644 --- a/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/view.hpp.jinja +++ b/chaotic-openapi/chaotic_openapi/back/cpp/handler/templates/view.hpp.jinja @@ -18,8 +18,9 @@ struct HandlerTag; class View final { public: using Deps = {{ userver }}::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = {{ userver }}::server::request::RequestContext; - static Response Handle(Request&& request, Deps&& deps); + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); /* Uncomment, if you want to define a custom logging for request/response body. * E.g. you want to log several fields, but omit the others (secrets, etc.). @@ -40,7 +41,7 @@ public: static std::string GetResponseForLogging( const Response& response, const std::string& serialized_response, - {{ userver }}::server::request::RequestContext& context); + RequestContext& context); */ }; diff --git a/chaotic-openapi/golden_tests/CMakeLists.txt b/chaotic-openapi/golden_tests/CMakeLists.txt index 0ce9100a7713..cf569cf83b76 100644 --- a/chaotic-openapi/golden_tests/CMakeLists.txt +++ b/chaotic-openapi/golden_tests/CMakeLists.txt @@ -9,7 +9,7 @@ userver_target_generate_openapi_client( ${PROJECT_NAME}-chgen-client NAME test OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/src/client" - FORMAT OFF + FORMAT ON SCHEMAS ${SCHEMAS} ) @@ -18,7 +18,7 @@ userver_target_generate_openapi_handlers( NAME test OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/src/handlers" SRC_DIR "${CMAKE_CURRENT_BINARY_DIR}/src/handlers" - FORMAT OFF + FORMAT ON SCHEMAS ${SCHEMAS} ) diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/client.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/client.hpp index 287d392fd44e..6f500673eaf0 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/client.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/client.hpp @@ -1,20 +1,22 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once +#include + #include "requests.hpp" #include "responses.hpp" -#include - namespace clients::test { class Client { -public: - /// POST /testme - /// A testing method to call - /// @throw testme::post::Exception + public: + /// POST /testme + /// A testing method to call + /// @throw testme::post::Exception - virtual testme::post::Response TestmePost(const testme::post::Request& request , const USERVER_NAMESPACE::chaotic::openapi::client::CommandControl& command_control = {}) = 0; + virtual testme::post::Response TestmePost( + const testme::post::Request& request, + const USERVER_NAMESPACE::chaotic::openapi::client::CommandControl& command_control = {}) = 0; virtual ~Client(); }; diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/client_fwd.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/client_fwd.hpp index ae04fca0c853..ad609574ced3 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/client_fwd.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/client_fwd.hpp @@ -5,4 +5,4 @@ namespace clients::test { class Client; -} // namespace clients::test +} // namespace clients::test diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/client_impl.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/client_impl.hpp index af6886e2c8e7..ea09376a6910 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/client_impl.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/client_impl.hpp @@ -2,47 +2,50 @@ #pragma once #include - #include #include +#include #include #include -#include - namespace clients::test { class ClientImpl final : public Client { -public: -// API + public: + // API -testme::post::Response TestmePost(const testme::post::Request& request , const USERVER_NAMESPACE::chaotic::openapi::client::CommandControl& command_control = {} -) override; + testme::post::Response TestmePost( + const testme::post::Request& request, + const USERVER_NAMESPACE::chaotic::openapi::client::CommandControl& command_control = {}) override; -// end of API + // end of API -static constexpr std::string_view kName = "test"; -static constexpr std::string_view kDefaultBaseUrl = "http://example.com"; + static constexpr std::string_view kName = "test"; + static constexpr std::string_view kDefaultBaseUrl = "http://example.com"; -ClientImpl(const USERVER_NAMESPACE::chaotic::openapi::client::Config& config, - USERVER_NAMESPACE::clients::http::Client& http_client); + ClientImpl(const USERVER_NAMESPACE::chaotic::openapi::client::Config& config, + USERVER_NAMESPACE::clients::http::Client& http_client); -static USERVER_NAMESPACE::yaml_config::Schema GetStaticConfigSchema(); + static USERVER_NAMESPACE::yaml_config::Schema GetStaticConfigSchema(); -void RegisterMiddleware(std::shared_ptr middleware) { -middleware_manager_.RegisterMiddleware(middleware); -} + void RegisterMiddleware(std::shared_ptr middleware) { + middleware_manager_.RegisterMiddleware(middleware); + } -void SetCoreMiddlewares(std::optional>> core_middlewares) { -core_middlewares_ = std::move(core_middlewares); -} + void SetCoreMiddlewares( + std::optional>> + core_middlewares) { + core_middlewares_ = std::move(core_middlewares); + } -private: -USERVER_NAMESPACE::chaotic::openapi::client::Config config_; -USERVER_NAMESPACE::clients::http::Client& http_client_; -USERVER_NAMESPACE::chaotic::openapi::MiddlewareManager middleware_manager_; -std::unordered_map> middlewares_; -std::optional>> core_middlewares_; + private: + USERVER_NAMESPACE::chaotic::openapi::client::Config config_; + USERVER_NAMESPACE::clients::http::Client& http_client_; + USERVER_NAMESPACE::chaotic::openapi::MiddlewareManager middleware_manager_; + std::unordered_map> + middlewares_; + std::optional>> + core_middlewares_; }; -} +} // namespace clients::test diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/component.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/component.hpp index 53effde5c49b..a7acb74fc194 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/component.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/component.hpp @@ -1,29 +1,29 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once +#include #include #include -#include - namespace clients::test { class Component final : public USERVER_NAMESPACE::components::ComponentBase { -public: - static constexpr std::string_view kName = "test-client"; + public: + static constexpr std::string_view kName = "test-client"; - Component(const USERVER_NAMESPACE::components::ComponentConfig& config, const USERVER_NAMESPACE::components::ComponentContext& context); + Component(const USERVER_NAMESPACE::components::ComponentConfig& config, + const USERVER_NAMESPACE::components::ComponentContext& context); - Client& GetClient(); + Client& GetClient(); - static USERVER_NAMESPACE::yaml_config::Schema GetStaticConfigSchema(); + static USERVER_NAMESPACE::yaml_config::Schema GetStaticConfigSchema(); -private: - ClientImpl client_; + private: + ClientImpl client_; }; } // namespace clients::test -template<> -inline constexpr auto USERVER_NAMESPACE::components::kConfigFileMode<::clients::test::Component> - = USERVER_NAMESPACE::components::ConfigFileMode::kNotRequired; +template <> +inline constexpr auto USERVER_NAMESPACE::components::kConfigFileMode<::clients::test::Component> = + USERVER_NAMESPACE::components::ConfigFileMode::kNotRequired; diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/exceptions.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/exceptions.hpp index d8052c29273a..b5008726d339 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/exceptions.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/exceptions.hpp @@ -6,28 +6,26 @@ namespace clients::test { /// @brief Base class for test client exceptions -class Exception: public USERVER_NAMESPACE::chaotic::openapi::client::Exception { +class Exception : public USERVER_NAMESPACE::chaotic::openapi::client::Exception { public: using USERVER_NAMESPACE::chaotic::openapi::client::Exception::Exception; ~Exception(); }; /// @brief Response with ErrorKind for test client exceptions -class HttpException : public USERVER_NAMESPACE::chaotic::openapi::client::HttpException -{ +class HttpException : public USERVER_NAMESPACE::chaotic::openapi::client::HttpException { public: - explicit HttpException(USERVER_NAMESPACE::clients::http::ErrorKind error_kind); + explicit HttpException(USERVER_NAMESPACE::clients::http::ErrorKind error_kind); }; /// @brief Response with HTTP status code for test client exceptions -class ExceptionWithStatusCode : public USERVER_NAMESPACE::chaotic::openapi::client::ExceptionWithStatusCode -{ +class ExceptionWithStatusCode : public USERVER_NAMESPACE::chaotic::openapi::client::ExceptionWithStatusCode { public: - ExceptionWithStatusCode(int status_code); + ExceptionWithStatusCode(int status_code); }; /// @brief Timeout exception class for test client exceptions -class TimeoutException: public USERVER_NAMESPACE::chaotic::openapi::client::TimeoutException { +class TimeoutException : public USERVER_NAMESPACE::chaotic::openapi::client::TimeoutException { public: using USERVER_NAMESPACE::chaotic::openapi::client::TimeoutException::TimeoutException; ~TimeoutException(); @@ -36,41 +34,32 @@ class TimeoutException: public USERVER_NAMESPACE::chaotic::openapi::client::Time namespace testme::post { /// @brief Base exception class for all client POST operations with URL '/testme' -class Exception: public ::clients::test::Exception { +class Exception : public ::clients::test::Exception { public: - const char* what() const noexcept override; + const char* what() const noexcept override; - static constexpr USERVER_NAMESPACE::utils::zstring_view kHandlerInfo{"POST /testme"}; + static constexpr USERVER_NAMESPACE::utils::zstring_view kHandlerInfo{"POST /testme"}; }; /// @brief Error response with ErrorKind for all client POST operations with URL '/testme' -class HttpException - : public Exception - , public ::clients::test::HttpException -{ - public: - using ::clients::test::HttpException::HttpException; - ~HttpException(); +class HttpException : public Exception, public ::clients::test::HttpException { + public: + using ::clients::test::HttpException::HttpException; + ~HttpException(); }; /// @brief Timeout exception class for all client POST operations with URL '/testme' -class TimeoutException - : public HttpException - , public ::clients::test::TimeoutException -{ - public: - TimeoutException(); - ~TimeoutException(); +class TimeoutException : public HttpException, public ::clients::test::TimeoutException { + public: + TimeoutException(); + ~TimeoutException(); }; /// @brief Error response with HTTP status code for all client POST operations with URL '/testme' -class ExceptionWithStatusCode - : public Exception - , public ::clients::test::ExceptionWithStatusCode -{ - public: - using ::clients::test::ExceptionWithStatusCode::ExceptionWithStatusCode; - ~ExceptionWithStatusCode(); +class ExceptionWithStatusCode : public Exception, public ::clients::test::ExceptionWithStatusCode { + public: + using ::clients::test::ExceptionWithStatusCode::ExceptionWithStatusCode; + ~ExceptionWithStatusCode(); }; } // namespace testme::post diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi.hpp index 1eff69f4bfdc..01c01fc18c32 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi.hpp @@ -1,14 +1,16 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once -#include "clients/test/openapi_fwd.hpp" - #include #include - #include -namespace clients {namespace test {namespace testme {namespace post { +#include "clients/test/openapi_fwd.hpp" + +namespace clients { +namespace test { +namespace testme { +namespace post { using Parameter1 = std::vector; diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_fwd.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_fwd.hpp index 81972c8a4194..3a9956cfaec1 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_fwd.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_fwd.hpp @@ -1,9 +1,10 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once -namespace clients {namespace test {namespace testme {namespace post { - -} // namespace post +namespace clients { +namespace test { +namespace testme { +namespace post {} // namespace post } // namespace testme } // namespace test } // namespace clients diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_parsers.ipp b/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_parsers.ipp index d409489a4259..f67ad3d8be28 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_parsers.ipp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_parsers.ipp @@ -1,16 +1,17 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once -#include "clients/test/openapi.hpp" - #include #include #include #include -namespace clients {namespace test {namespace testme {namespace post { +#include "clients/test/openapi.hpp" -} // namespace post +namespace clients { +namespace test { +namespace testme { +namespace post {} // namespace post } // namespace testme } // namespace test } // namespace clients diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_sax_parsers.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_sax_parsers.hpp index 99d0911c66a0..f444a24c1666 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_sax_parsers.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/openapi_sax_parsers.hpp @@ -1,17 +1,18 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once -#include "clients/test/openapi.hpp" - #include #include +#include #include #include -#include -namespace clients {namespace test {namespace testme {namespace post { +#include "clients/test/openapi.hpp" -} // namespace post +namespace clients { +namespace test { +namespace testme { +namespace post {} // namespace post } // namespace testme } // namespace test } // namespace clients diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/qos.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/qos.hpp index 5055dc60d306..632dc7ed0137 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/qos.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/qos.hpp @@ -6,6 +6,6 @@ namespace clients::test { inline const USERVER_NAMESPACE::dynamic_config::Key -kQosConfig{"", USERVER_NAMESPACE::dynamic_config::DefaultAsJsonString{"{}"}}; + kQosConfig{"", USERVER_NAMESPACE::dynamic_config::DefaultAsJsonString{"{}"}}; } // namespace clients::test diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/requests.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/requests.hpp index abaefbc0e17c..9c099753bfca 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/requests.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/requests.hpp @@ -1,28 +1,25 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once +#include +#include #include - #include -#include - -#include namespace clients::test { -namespace testme::post { using Body = int; +namespace testme::post { +using Body = int; struct Request { -std::string -number; -std::vector -array; - - Body body; + std::string number; + std::vector array; + Body body; }; -void SerializeRequest(const Request& request, const std::string& base_url, USERVER_NAMESPACE::clients::http::Request& http_request); -} +void SerializeRequest(const Request& request, const std::string& base_url, + USERVER_NAMESPACE::clients::http::Request& http_request); +} // namespace testme::post -} +} // namespace clients::test diff --git a/chaotic-openapi/golden_tests/output/client/include/clients/test/responses.hpp b/chaotic-openapi/golden_tests/output/client/include/clients/test/responses.hpp index ac3c0d263f96..0d70d64fabfa 100644 --- a/chaotic-openapi/golden_tests/output/client/include/clients/test/responses.hpp +++ b/chaotic-openapi/golden_tests/output/client/include/clients/test/responses.hpp @@ -1,13 +1,11 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once -#include - #include -#include -#include - #include +#include +#include +#include USERVER_NAMESPACE_BEGIN namespace clients::http { @@ -19,14 +17,13 @@ namespace clients::test { namespace testme::post { - struct Response200{ - std::optionalX_Header; - - }; +struct Response200 { + std::optional X_Header; +}; - using Response =Response200; +using Response = Response200; Response ParseResponse(USERVER_NAMESPACE::clients::http::Response& response); -} +} // namespace testme::post -} +} // namespace clients::test diff --git a/chaotic-openapi/golden_tests/output/client/src/clients/test/client_impl.cpp b/chaotic-openapi/golden_tests/output/client/src/clients/test/client_impl.cpp index f659fd87e47e..48d6a59bb064 100644 --- a/chaotic-openapi/golden_tests/output/client/src/clients/test/client_impl.cpp +++ b/chaotic-openapi/golden_tests/output/client/src/clients/test/client_impl.cpp @@ -1,40 +1,38 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #include - -#include #include +#include #include namespace clients::test { -ClientImpl::ClientImpl( - const USERVER_NAMESPACE::chaotic::openapi::client::Config& config, - USERVER_NAMESPACE::clients::http::Client& http_client -) - : config_(config), http_client_(http_client) -{} +ClientImpl::ClientImpl(const USERVER_NAMESPACE::chaotic::openapi::client::Config& config, + USERVER_NAMESPACE::clients::http::Client& http_client) + : config_(config), http_client_(http_client) {} -testme::post::Response ClientImpl::TestmePost(const testme::post::Request& request , const USERVER_NAMESPACE::chaotic::openapi::client::CommandControl& command_control -) { -auto r = http_client_.CreateRequest(); -r.SetUrlTemplate("/testme"); +testme::post::Response ClientImpl::TestmePost( + const testme::post::Request& request, + const USERVER_NAMESPACE::chaotic::openapi::client::CommandControl& command_control) { + auto r = http_client_.CreateRequest(); + r.SetUrlTemplate("/testme"); -if (core_middlewares_) { + if (core_middlewares_) { r.SetMiddlewaresList(*core_middlewares_); -} -ApplyConfig(r, command_control, config_); SerializeRequest(request, config_.base_url, r); + } + ApplyConfig(r, command_control, config_); + SerializeRequest(request, config_.base_url, r); -middleware_manager_.ProcessRequest(r); + middleware_manager_.ProcessRequest(r); -std::shared_ptr response; -try { + std::shared_ptr response; + try { response = r.perform(); middleware_manager_.ProcessResponse(*response); -} catch (const USERVER_NAMESPACE::clients::http::TimeoutException& e) { + } catch (const USERVER_NAMESPACE::clients::http::TimeoutException& e) { throw testme::post::TimeoutException(); -} + } -return testme::post::ParseResponse(*response); + return testme::post::ParseResponse(*response); } } // namespace clients::test diff --git a/chaotic-openapi/golden_tests/output/client/src/clients/test/component.cpp b/chaotic-openapi/golden_tests/output/client/src/clients/test/component.cpp index fcf15fdb2527..3ea3562802a4 100644 --- a/chaotic-openapi/golden_tests/output/client/src/clients/test/component.cpp +++ b/chaotic-openapi/golden_tests/output/client/src/clients/test/component.cpp @@ -1,78 +1,71 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #include - #include #include +#include #include #include #include #include -#include - namespace clients::test { -Component::Component( - const USERVER_NAMESPACE::components::ComponentConfig& config, - const USERVER_NAMESPACE::components::ComponentContext& context -) +Component::Component(const USERVER_NAMESPACE::components::ComponentConfig& config, + const USERVER_NAMESPACE::components::ComponentContext& context) : USERVER_NAMESPACE::components::ComponentBase(config, context), - client_( - USERVER_NAMESPACE::chaotic::openapi::client::ParseConfig(config, ClientImpl::kDefaultBaseUrl), - context.FindComponent().GetHttpClient() - ) -{ - if (config.HasMember("middlewares")) { - const auto& mw_config = config["middlewares"]; + client_(USERVER_NAMESPACE::chaotic::openapi::client::ParseConfig(config, ClientImpl::kDefaultBaseUrl), + context.FindComponent().GetHttpClient()) { + if (config.HasMember("middlewares")) { + const auto& mw_config = config["middlewares"]; - for (const auto& [name, config] : USERVER_NAMESPACE::formats::common::Items(mw_config)) { - auto& factory = context.FindComponent< - USERVER_NAMESPACE::chaotic::openapi::client::MiddlewareFactory>("chaotic-client-middleware-" + name); - auto middleware = factory.Create(config); - client_.RegisterMiddleware(middleware); - } + for (const auto& [name, config] : USERVER_NAMESPACE::formats::common::Items(mw_config)) { + auto& factory = context.FindComponent( + "chaotic-client-middleware-" + name); + auto middleware = factory.Create(config); + client_.RegisterMiddleware(middleware); + } - const auto& names = config["core-middlewares"].As>>(std::nullopt); - std::optional>> core_middlewares; - if (names) { - core_middlewares.emplace(); - for (const auto& name : *names) { - auto& component = context.FindComponent< - USERVER_NAMESPACE::clients::http::middlewares::ComponentBase>(name); - core_middlewares->emplace_back(&component.GetMiddleware()); - } - } - client_.SetCoreMiddlewares(std::move(core_middlewares)); + const auto& names = config["core-middlewares"].As>>(std::nullopt); + std::optional>> + core_middlewares; + if (names) { + core_middlewares.emplace(); + for (const auto& name : *names) { + auto& component = context.FindComponent(name); + core_middlewares->emplace_back(&component.GetMiddleware()); + } } + client_.SetCoreMiddlewares(std::move(core_middlewares)); + } } Client& Component::GetClient() { return client_; } USERVER_NAMESPACE::yaml_config::Schema Component::GetStaticConfigSchema() { - std::string base_schema = R"( -type: object -description: OpenAPI HTTP client with middlewares -additionalProperties: false -properties: - base-url: - type: string - description: Base URL for the API - timeout-ms: - type: integer - description: Request timeout in milliseconds - minimum: 1 - attempts: - type: integer - description: Maximum number of retry attempts - minimum: 1 - middlewares: + std::string base_schema = R"( type: object - description: Middlewares configuration - additionalProperties: true - properties: {} -)"; + description: OpenAPI HTTP client with middlewares + additionalProperties: false + properties: + base-url: + type: string + description: Base URL for the API + timeout-ms: + type: integer + description: Request timeout in milliseconds + minimum: 1 + attempts: + type: integer + description: Maximum number of retry attempts + minimum: 1 + middlewares: + type: object + description: Middlewares configuration + additionalProperties: true + properties: {} + )"; - return USERVER_NAMESPACE::yaml_config::MergeSchemas(base_schema); + return USERVER_NAMESPACE::yaml_config::MergeSchemas(base_schema); } -} +} // namespace clients::test diff --git a/chaotic-openapi/golden_tests/output/client/src/clients/test/exceptions.cpp b/chaotic-openapi/golden_tests/output/client/src/clients/test/exceptions.cpp index 67050542f69a..1c96c7bab001 100644 --- a/chaotic-openapi/golden_tests/output/client/src/clients/test/exceptions.cpp +++ b/chaotic-openapi/golden_tests/output/client/src/clients/test/exceptions.cpp @@ -1,6 +1,5 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #include - #include namespace clients::test { @@ -8,26 +7,20 @@ namespace clients::test { Exception::~Exception() = default; HttpException::HttpException(USERVER_NAMESPACE::clients::http::ErrorKind error_kind) - : USERVER_NAMESPACE::chaotic::openapi::client::HttpException(error_kind) -{} + : USERVER_NAMESPACE::chaotic::openapi::client::HttpException(error_kind) {} ExceptionWithStatusCode::ExceptionWithStatusCode(int status_code) - : USERVER_NAMESPACE::chaotic::openapi::client::ExceptionWithStatusCode(status_code) -{} + : USERVER_NAMESPACE::chaotic::openapi::client::ExceptionWithStatusCode(status_code) {} TimeoutException::~TimeoutException() = default; namespace testme::post { -const char* Exception::what() const noexcept { - return kHandlerInfo.c_str(); -} +const char* Exception::what() const noexcept { return kHandlerInfo.c_str(); } HttpException::~HttpException() = default; -TimeoutException::TimeoutException() - : HttpException(USERVER_NAMESPACE::clients::http::ErrorKind::kTimeout) -{} +TimeoutException::TimeoutException() : HttpException(USERVER_NAMESPACE::clients::http::ErrorKind::kTimeout) {} TimeoutException::~TimeoutException() = default; diff --git a/chaotic-openapi/golden_tests/output/client/src/clients/test/openapi.cpp b/chaotic-openapi/golden_tests/output/client/src/clients/test/openapi.cpp index 5b4d9f566ab5..ecc26e83c162 100644 --- a/chaotic-openapi/golden_tests/output/client/src/clients/test/openapi.cpp +++ b/chaotic-openapi/golden_tests/output/client/src/clients/test/openapi.cpp @@ -1,15 +1,14 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ -#include "clients/test/openapi.hpp" - #include +#include "clients/test/openapi.hpp" #include "clients/test/openapi_parsers.ipp" - #include "clients/test/openapi_sax_parsers.hpp" -namespace clients {namespace test {namespace testme {namespace post { - -} // namespace post +namespace clients { +namespace test { +namespace testme { +namespace post {} // namespace post } // namespace testme } // namespace test } // namespace clients diff --git a/chaotic-openapi/golden_tests/output/client/src/clients/test/requests.cpp b/chaotic-openapi/golden_tests/output/client/src/clients/test/requests.cpp index 7680e5a2079e..ffa27805b8e3 100644 --- a/chaotic-openapi/golden_tests/output/client/src/clients/test/requests.cpp +++ b/chaotic-openapi/golden_tests/output/client/src/clients/test/requests.cpp @@ -1,38 +1,36 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #include - +#include #include +#include #include #include -#include #include -#include -#include +#include namespace clients::test { namespace openapi = USERVER_NAMESPACE::chaotic::openapi; -namespace testme::post { static constexpr openapi::Name knumber = "number"; +namespace testme::post { +static constexpr openapi::Name knumber = "number"; static constexpr openapi::Name karray = "array"; -void SerializeRequest(const Request& request, const std::string& base_url, USERVER_NAMESPACE::clients::http::Request& http_request) -{ -openapi::ParameterSinkHttpClient sink( -http_request, -base_url + "/testme" -); +void SerializeRequest(const Request& request, const std::string& base_url, + USERVER_NAMESPACE::clients::http::Request& http_request) { + openapi::ParameterSinkHttpClient sink(http_request, base_url + "/testme"); -openapi::WriteParameter>(request.number, sink); -openapi::WriteParameter>(request.array, sink); + openapi::WriteParameter>( + request.number, sink); + openapi::WriteParameter>( + request.array, sink); -http_request.data(ToString(USERVER_NAMESPACE::formats::json::ValueBuilder(request.body).ExtractValue())); - -sink.Flush(); + http_request.data(ToString(USERVER_NAMESPACE::formats::json::ValueBuilder(request.body).ExtractValue())); + sink.Flush(); } -} // namespace +} // namespace testme::post -} +} // namespace clients::test diff --git a/chaotic-openapi/golden_tests/output/client/src/clients/test/responses.cpp b/chaotic-openapi/golden_tests/output/client/src/clients/test/responses.cpp index 1de95af070b9..df3cc7e81994 100644 --- a/chaotic-openapi/golden_tests/output/client/src/clients/test/responses.cpp +++ b/chaotic-openapi/golden_tests/output/client/src/clients/test/responses.cpp @@ -1,43 +1,38 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #include - +#include +#include #include #include #include #include #include -#include - -#include namespace clients::test { namespace testme::post { -Response ParseResponse(USERVER_NAMESPACE::clients::http::Response& http_response) -{ -auto status_code = static_cast(http_response.status_code()); -switch (status_code) { - case 200: - { - Response200 r{}; +Response ParseResponse(USERVER_NAMESPACE::clients::http::Response& http_response) { + auto status_code = static_cast(http_response.status_code()); + switch (status_code) { + case 200: { + Response200 r{}; - { - static const USERVER_NAMESPACE::http::headers::PredefinedHeader kHeader("X-Header"); - auto it = http_response.headers().find(kHeader); - if (it != http_response.headers().end()) { - namespace openapi = USERVER_NAMESPACE::chaotic::openapi; - static constexpr openapi::Name kX_Header = "X-Header"; - using Header = openapi::TrivialParameter; - r.X_Header = openapi::ParameterParser::Parse(std::string{it->second}); + { + static const USERVER_NAMESPACE::http::headers::PredefinedHeader kHeader("X-Header"); + auto it = http_response.headers().find(kHeader); + if (it != http_response.headers().end()) { + namespace openapi = USERVER_NAMESPACE::chaotic::openapi; + static constexpr openapi::Name kX_Header = "X-Header"; + using Header = openapi::TrivialParameter; + r.X_Header = openapi::ParameterParser::Parse(std::string{it->second}); + } } - } return r; + } + default: + throw ExceptionWithStatusCode(status_code); } - -default: - throw ExceptionWithStatusCode(status_code); -} -} -} } +} // namespace testme::post +} // namespace clients::test diff --git a/chaotic-openapi/golden_tests/output/handlers/handlers/test/testme/post/view.cpp b/chaotic-openapi/golden_tests/output/handlers/handlers/test/testme/post/view.cpp index 9a66d6a1a171..4d3b9c658a13 100644 --- a/chaotic-openapi/golden_tests/output/handlers/handlers/test/testme/post/view.cpp +++ b/chaotic-openapi/golden_tests/output/handlers/handlers/test/testme/post/view.cpp @@ -2,32 +2,32 @@ namespace handlers::test::testme::post { -Response View::Handle(Request&& /*request*/, Deps&& /*deps*/) { -// Handle request using dependencies from Deps (clients, caches, configs, databases...) -return {}; +Response View::Handle(Request&& /*request*/, Deps&& /*deps*/, RequestContext& /*context*/) { + // Handle request using dependencies from Deps (clients, caches, configs, databases...) + return {}; } /* std::string View::GetRequestBodyForLogging( -const USERVER_NAMESPACE::formats::json::Value& body) { -(void)body; -return {}; + const USERVER_NAMESPACE::formats::json::Value& body) { + (void)body; + return {}; } std::string View::GetInvalidRequestBodyForLogging( -const USERVER_NAMESPACE::server::http::HttpRequest& request) { -(void)request; -return {}; + const USERVER_NAMESPACE::server::http::HttpRequest& request) { + (void)request; + return {}; } std::string View::GetResponseForLogging( -const Response& response, -const std::string& serialized_response, -USERVER_NAMESPACE::server::request::RequestContext& context) { -(void)response; -(void)serialized_response; -(void)context; -return {}; + const Response& response, + const std::string& serialized_response, + RequestContext& context) { + (void)response; + (void)serialized_response; + (void)context; + return {}; } */ diff --git a/chaotic-openapi/golden_tests/output/handlers/handlers/test/testme/post/view.hpp b/chaotic-openapi/golden_tests/output/handlers/handlers/test/testme/post/view.hpp index 0e8b698cdc86..064cf6fb974a 100644 --- a/chaotic-openapi/golden_tests/output/handlers/handlers/test/testme/post/view.hpp +++ b/chaotic-openapi/golden_tests/output/handlers/handlers/test/testme/post/view.hpp @@ -1,39 +1,39 @@ #pragma once +#include +#include #include - #include +#include #include #include -#include -#include -#include namespace handlers::test::testme::post { struct HandlerTag; class View final { -public: -using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; - -static Response Handle(Request&& request, Deps&& deps); - -/* Uncomment, if you want to define a custom logging for request/response body. -* E.g. you want to log several fields, but omit the others (secrets, etc.). -* -static std::string GetRequestBodyForLogging( -const USERVER_NAMESPACE::formats::json::Value& body); - -// Logger for 'invalid JSON body' request -static std::string GetInvalidRequestBodyForLogging( -const USERVER_NAMESPACE::server::http::HttpRequest& request); - -static std::string GetResponseForLogging( -const Response& response, -const std::string& serialized_response, -USERVER_NAMESPACE::server::request::RequestContext& context); -*/ + public: + using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; + + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); + + /* Uncomment, if you want to define a custom logging for request/response body. + * E.g. you want to log several fields, but omit the others (secrets, etc.). + * + static std::string GetRequestBodyForLogging( + const USERVER_NAMESPACE::formats::json::Value& body); + + // Logger for 'invalid JSON body' request + static std::string GetInvalidRequestBodyForLogging( + const USERVER_NAMESPACE::server::http::HttpRequest& request); + + static std::string GetResponseForLogging( + const Response& response, + const std::string& serialized_response, + RequestContext& context); + */ }; } // namespace handlers::test::testme::post diff --git a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/chaotic_handlers_list.hpp b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/chaotic_handlers_list.hpp index 05e6cc5c9511..e22bcff1dc66 100644 --- a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/chaotic_handlers_list.hpp +++ b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/chaotic_handlers_list.hpp @@ -16,11 +16,7 @@ namespace handlers::test { /// component_list.AppendComponentList(handlers::test::ChaoticHandlersList()); /// @endcode inline USERVER_NAMESPACE::components::ComponentList ChaoticHandlersList() { -return USERVER_NAMESPACE::components::ComponentList() -.Append>() -.Append() -; + return USERVER_NAMESPACE::components::ComponentList().Append(); } } // namespace handlers::test diff --git a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi.hpp b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi.hpp index 88e92f076632..906ce98ed249 100644 --- a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi.hpp +++ b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi.hpp @@ -1,14 +1,16 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once -#include "handlers/test/openapi_fwd.hpp" - #include #include - #include -namespace handlers {namespace test {namespace testme {namespace post { +#include "handlers/test/openapi_fwd.hpp" + +namespace handlers { +namespace test { +namespace testme { +namespace post { using Parameter1 = std::vector; diff --git a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_fwd.hpp b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_fwd.hpp index cffea112db44..fa5676d6b984 100644 --- a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_fwd.hpp +++ b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_fwd.hpp @@ -1,9 +1,10 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once -namespace handlers {namespace test {namespace testme {namespace post { - -} // namespace post +namespace handlers { +namespace test { +namespace testme { +namespace post {} // namespace post } // namespace testme } // namespace test } // namespace handlers diff --git a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_parsers.ipp b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_parsers.ipp index 77d9ce1b1925..df108e57cc5e 100644 --- a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_parsers.ipp +++ b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_parsers.ipp @@ -1,16 +1,17 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once -#include "handlers/test/openapi.hpp" - #include #include #include #include -namespace handlers {namespace test {namespace testme {namespace post { +#include "handlers/test/openapi.hpp" -} // namespace post +namespace handlers { +namespace test { +namespace testme { +namespace post {} // namespace post } // namespace testme } // namespace test } // namespace handlers diff --git a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_sax_parsers.hpp b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_sax_parsers.hpp index 1327f77542df..111ccdfdb2e2 100644 --- a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_sax_parsers.hpp +++ b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/openapi_sax_parsers.hpp @@ -1,17 +1,18 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once -#include "handlers/test/openapi.hpp" - #include #include +#include #include #include -#include -namespace handlers {namespace test {namespace testme {namespace post { +#include "handlers/test/openapi.hpp" -} // namespace post +namespace handlers { +namespace test { +namespace testme { +namespace post {} // namespace post } // namespace testme } // namespace test } // namespace handlers diff --git a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/handler.hpp b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/handler.hpp index 2ebdaa217645..5324d16f5778 100644 --- a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/handler.hpp +++ b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/handler.hpp @@ -4,7 +4,6 @@ #include #include #include - #include namespace handlers::test::testme::post { @@ -16,12 +15,7 @@ namespace impl { inline constexpr std::string_view kHandlerName = "handler-testme-post"; } -using Handler = USERVER_NAMESPACE::chaotic::openapi::server::BaseHandler< -impl::kHandlerName, -void, -Request, -Response, -HandlerTag, -View>; +using Handler = USERVER_NAMESPACE::chaotic::openapi::server::BaseHandler; } // namespace handlers::test::testme::post diff --git a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/requests.hpp b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/requests.hpp index dcb338727d27..95e003f495b3 100644 --- a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/requests.hpp +++ b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/requests.hpp @@ -1,13 +1,12 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #pragma once +#include +#include #include #include #include #include -#include - -#include namespace handlers::test::testme::post { @@ -16,14 +15,13 @@ static constexpr USERVER_NAMESPACE::chaotic::openapi::Name karray = "array"; /// Request parsed from HttpRequest for this operation. struct Request final { - std::string number; - std::vector array; + std::string number; + std::vector array; - int body; + int body; }; -Request ParseRequest( -const USERVER_NAMESPACE::server::http::HttpRequest& http_request, -const USERVER_NAMESPACE::chaotic::openapi::To&); +Request ParseRequest(const USERVER_NAMESPACE::server::http::HttpRequest& http_request, + const USERVER_NAMESPACE::chaotic::openapi::To&); } // namespace handlers::test::testme::post diff --git a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/responses.hpp b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/responses.hpp index 8e9915d91e93..0d31b2eed32b 100644 --- a/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/responses.hpp +++ b/chaotic-openapi/golden_tests/output/handlers/include/handlers/test/testme/post/responses.hpp @@ -2,20 +2,19 @@ #pragma once #include +#include +#include #include -#include - #include #include -#include -#include +#include namespace handlers::test::testme::post { struct Response200 final { -static constexpr int kStatus = 200; + static constexpr int kStatus = 200; - std::optional X_Header; + std::optional X_Header; }; /// All possible responses for this operation. diff --git a/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/openapi.cpp b/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/openapi.cpp index 4446de2e2821..5fc07e633f8f 100644 --- a/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/openapi.cpp +++ b/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/openapi.cpp @@ -1,15 +1,14 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ -#include "handlers/test/openapi.hpp" - #include +#include "handlers/test/openapi.hpp" #include "handlers/test/openapi_parsers.ipp" - #include "handlers/test/openapi_sax_parsers.hpp" -namespace handlers {namespace test {namespace testme {namespace post { - -} // namespace post +namespace handlers { +namespace test { +namespace testme { +namespace post {} // namespace post } // namespace testme } // namespace test } // namespace handlers diff --git a/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/testme/post/requests.cpp b/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/testme/post/requests.cpp index 01fd1cee1add..d6005d3a3fc1 100644 --- a/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/testme/post/requests.cpp +++ b/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/testme/post/requests.cpp @@ -1,26 +1,26 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #include - #include -#include #include #include +#include namespace handlers::test::testme::post { -Request ParseRequest( -const USERVER_NAMESPACE::server::http::HttpRequest& http_request, -const USERVER_NAMESPACE::chaotic::openapi::To& /*tag*/) { -namespace openapi = USERVER_NAMESPACE::chaotic::openapi; +Request ParseRequest(const USERVER_NAMESPACE::server::http::HttpRequest& http_request, + const USERVER_NAMESPACE::chaotic::openapi::To& /*tag*/) { + namespace openapi = USERVER_NAMESPACE::chaotic::openapi; -Request r{}; - r.number = openapi::ReadParameter>(http_request); - r.array = openapi::ReadParameter>(http_request); + Request r{}; + r.number = openapi::ReadParameter>( + http_request); + r.array = openapi::ReadParameter>( + http_request); - auto json = USERVER_NAMESPACE::formats::json::FromString(http_request.RequestBody()); -r.body = json.As(); + auto json = USERVER_NAMESPACE::formats::json::FromString(http_request.RequestBody()); + r.body = json.As(); -return r; + return r; } } // namespace handlers::test::testme::post diff --git a/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/testme/post/responses.cpp b/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/testme/post/responses.cpp index 73b5a1ed2942..cf2270dc2885 100644 --- a/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/testme/post/responses.cpp +++ b/chaotic-openapi/golden_tests/output/handlers/src/handlers/test/testme/post/responses.cpp @@ -1,35 +1,33 @@ /* THIS FILE IS AUTOGENERATED, DON'T EDIT! */ #include - -#include -#include -#include #include #include #include +#include +#include +#include namespace handlers::test::testme::post { namespace { std::string SerializeSpecificResponse(const Response200& r, - USERVER_NAMESPACE::server::http::HttpRequest& http_request) { -http_request.GetHttpResponse().SetStatus( -static_cast(200) -); -namespace openapi = USERVER_NAMESPACE::chaotic::openapi; - static constexpr openapi::Name kX_Header = "X-Header"; -openapi::server::ParameterSinkHttpResponse header_sink(http_request.GetHttpResponse()); - if (r.X_Header) { - openapi::WriteParameter>(*r.X_Header, header_sink); - } -return {}; + USERVER_NAMESPACE::server::http::HttpRequest& http_request) { + http_request.GetHttpResponse().SetStatus(static_cast(200)); + namespace openapi = USERVER_NAMESPACE::chaotic::openapi; + static constexpr openapi::Name kX_Header = "X-Header"; + openapi::server::ParameterSinkHttpResponse header_sink(http_request.GetHttpResponse()); + if (r.X_Header) { + openapi::WriteParameter>( + *r.X_Header, header_sink); + } + return {}; } } // namespace std::string SerializeResponse(const Response& response, USERVER_NAMESPACE::server::http::HttpRequest& http_request) { -return SerializeSpecificResponse(response, http_request); + return SerializeSpecificResponse(response, http_request); } } // namespace handlers::test::testme::post diff --git a/chaotic-openapi/include/userver/chaotic/openapi/server/handler_base.hpp b/chaotic-openapi/include/userver/chaotic/openapi/server/handler_base.hpp index f365ad76607a..d7c4c1e96073 100644 --- a/chaotic-openapi/include/userver/chaotic/openapi/server/handler_base.hpp +++ b/chaotic-openapi/include/userver/chaotic/openapi/server/handler_base.hpp @@ -121,8 +121,7 @@ class BaseHandler final : public USERVER_NAMESPACE::server::handlers::HttpHandle const USERVER_NAMESPACE::components::ComponentContext& context ) : USERVER_NAMESPACE::server::handlers::HttpHandlerBase(config, context), - factories_(context.FindComponent()) - {} + factories_(context.FindComponent()) {} ~BaseHandler() override = default; @@ -142,6 +141,16 @@ class BaseHandler final : public USERVER_NAMESPACE::server::handlers::HttpHandle "View::GetInvalidRequestBodyForLogging requires " "View::GetRequestBodyForLogging(const formats::json::Value&)." ); + static_assert( + requires(Request&& r, Deps&& d, USERVER_NAMESPACE::server::request::RequestContext& ctx) { + { + View::Handle(std::move(r), std::move(d), ctx) + } -> std::convertible_to; + }, + "View::Handle must accept server::request::RequestContext as the third parameter: " + "static Response Handle(Request&& request, Deps&& deps, RequestContext& context). " + "The legacy 2-argument Handle(Request&&, Deps&&) is no longer supported." + ); using Factories = chaotic::openapi::server::dependencies::Factories; using FactoriesContainer = USERVER_NAMESPACE::components::Container; @@ -165,7 +174,7 @@ class BaseHandler final : public USERVER_NAMESPACE::server::handlers::HttpHandle USERVER_NAMESPACE::server::request::RequestContext& context ) const { auto deps = factories_.Get().template Make(); - auto response = View::Handle(std::move(request), std::move(deps)); + auto response = View::Handle(std::move(request), std::move(deps), context); auto serialized = SerializeResponse(response, http_request); if constexpr (impl::ViewHasGetResponseForLogging) { context.SetData< diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/formpost/view.cpp b/chaotic-openapi/integration_tests/src/handlers/simple/formpost/view.cpp index b3df40619e97..c84a8b8228d6 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/formpost/view.cpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/formpost/view.cpp @@ -2,14 +2,20 @@ namespace handlers::simple::formpost { -Response View::Handle(Request&& /*request*/, Deps&& /*deps*/) { return {}; } +Response View::Handle( + Request&& /*request*/, + Deps&& /*deps*/, + RequestContext& /*context*/ +) { + return {}; +} std::string View::GetRequestBodyForLogging(const std::string& /*body*/) { return {}; } std::string View::GetResponseForLogging( const Response& /*response*/, const std::string& /*serialized_response*/, - USERVER_NAMESPACE::server::request::RequestContext& /*context*/ + RequestContext& /*context*/ ) { return {}; } diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/formpost/view.hpp b/chaotic-openapi/integration_tests/src/handlers/simple/formpost/view.hpp index ffa447675964..894547cb4559 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/formpost/view.hpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/formpost/view.hpp @@ -14,15 +14,16 @@ struct HandlerTag; class View final { public: using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; - static Response Handle(Request&& request, Deps&& deps); + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); static std::string GetRequestBodyForLogging(const std::string& body); static std::string GetResponseForLogging( const Response& response, const std::string& serialized_response, - USERVER_NAMESPACE::server::request::RequestContext& context + RequestContext& context ); }; diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/greetget/view.cpp b/chaotic-openapi/integration_tests/src/handlers/simple/greetget/view.cpp index 36fb1495652a..fab4cd61053a 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/greetget/view.cpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/greetget/view.cpp @@ -2,12 +2,18 @@ namespace handlers::simple::greetget { -Response View::Handle(Request&& /*request*/, Deps&& /*deps*/) { return {}; } +Response View::Handle( + Request&& /*request*/, + Deps&& /*deps*/, + RequestContext& /*context*/ +) { + return {}; +} std::string View::GetResponseForLogging( const Response& /*response*/, const std::string& /*serialized_response*/, - USERVER_NAMESPACE::server::request::RequestContext& /*context*/ + RequestContext& /*context*/ ) { return {}; } diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/greetget/view.hpp b/chaotic-openapi/integration_tests/src/handlers/simple/greetget/view.hpp index 25b600c8ae14..488edbe6c992 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/greetget/view.hpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/greetget/view.hpp @@ -14,13 +14,14 @@ struct HandlerTag; class View final { public: using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; - static Response Handle(Request&& request, Deps&& deps); + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); static std::string GetResponseForLogging( const Response& response, const std::string& serialized_response, - USERVER_NAMESPACE::server::request::RequestContext& context + RequestContext& context ); }; diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/headersget/view.cpp b/chaotic-openapi/integration_tests/src/handlers/simple/headersget/view.cpp index b00977a09d0c..566cc16eea06 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/headersget/view.cpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/headersget/view.cpp @@ -2,12 +2,18 @@ namespace handlers::simple::headersget { -Response View::Handle(Request&& /*request*/, Deps&& /*deps*/) { return {}; } +Response View::Handle(Request&& /*request*/, Deps&& /*deps*/, RequestContext& context) { + Response200 response; + const auto* user_id = context.GetDataOptional("x-user-id"); + response.X_String = user_id ? *user_id : ""; + response.body = response.X_String; + return response; +} std::string View::GetResponseForLogging( const Response& /*response*/, const std::string& /*serialized_response*/, - USERVER_NAMESPACE::server::request::RequestContext& /*context*/ + RequestContext& /*context*/ ) { return {}; } diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/headersget/view.hpp b/chaotic-openapi/integration_tests/src/handlers/simple/headersget/view.hpp index 7ed98bd5ae34..710d491c2dea 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/headersget/view.hpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/headersget/view.hpp @@ -14,13 +14,14 @@ struct HandlerTag; class View final { public: using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; - static Response Handle(Request&& request, Deps&& deps); + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); static std::string GetResponseForLogging( const Response& response, const std::string& serialized_response, - USERVER_NAMESPACE::server::request::RequestContext& context + RequestContext& context ); }; diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/multipartpost/view.cpp b/chaotic-openapi/integration_tests/src/handlers/simple/multipartpost/view.cpp index 4610810ed9da..e1ee3a64b5ef 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/multipartpost/view.cpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/multipartpost/view.cpp @@ -2,14 +2,20 @@ namespace handlers::simple::multipartpost { -Response View::Handle(Request&& /*request*/, Deps&& /*deps*/) { return {}; } +Response View::Handle( + Request&& /*request*/, + Deps&& /*deps*/, + RequestContext& /*context*/ +) { + return {}; +} std::string View::GetRequestBodyForLogging(const std::string& /*body*/) { return {}; } std::string View::GetResponseForLogging( const Response& /*response*/, const std::string& /*serialized_response*/, - USERVER_NAMESPACE::server::request::RequestContext& /*context*/ + RequestContext& /*context*/ ) { return {}; } diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/multipartpost/view.hpp b/chaotic-openapi/integration_tests/src/handlers/simple/multipartpost/view.hpp index 96991cc475ee..ac71a51e6c81 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/multipartpost/view.hpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/multipartpost/view.hpp @@ -14,15 +14,16 @@ struct HandlerTag; class View final { public: using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; - static Response Handle(Request&& request, Deps&& deps); + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); static std::string GetRequestBodyForLogging(const std::string& body); static std::string GetResponseForLogging( const Response& response, const std::string& serialized_response, - USERVER_NAMESPACE::server::request::RequestContext& context + RequestContext& context ); }; diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/multipost/view.cpp b/chaotic-openapi/integration_tests/src/handlers/simple/multipost/view.cpp index bd2ced69fa03..3808770c3487 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/multipost/view.cpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/multipost/view.cpp @@ -2,12 +2,18 @@ namespace handlers::simple::multipost { -Response View::Handle(Request&& /*request*/, Deps&& /*deps*/) { return {}; } +Response View::Handle( + Request&& /*request*/, + Deps&& /*deps*/, + RequestContext& /*context*/ +) { + return {}; +} std::string View::GetResponseForLogging( const Response& /*response*/, const std::string& /*serialized_response*/, - USERVER_NAMESPACE::server::request::RequestContext& /*context*/ + RequestContext& /*context*/ ) { return {}; } diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/multipost/view.hpp b/chaotic-openapi/integration_tests/src/handlers/simple/multipost/view.hpp index d4632407af85..23b03d2fac85 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/multipost/view.hpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/multipost/view.hpp @@ -14,13 +14,14 @@ struct HandlerTag; class View final { public: using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; - static Response Handle(Request&& request, Deps&& deps); + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); static std::string GetResponseForLogging( const Response& response, const std::string& serialized_response, - USERVER_NAMESPACE::server::request::RequestContext& context + RequestContext& context ); }; diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/octetget/view.cpp b/chaotic-openapi/integration_tests/src/handlers/simple/octetget/view.cpp index b121f0a03227..5ccfb1f648af 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/octetget/view.cpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/octetget/view.cpp @@ -2,14 +2,20 @@ namespace handlers::simple::octetget { -Response View::Handle(Request&& /*request*/, Deps&& /*deps*/) { return {}; } +Response View::Handle( + Request&& /*request*/, + Deps&& /*deps*/, + RequestContext& /*context*/ +) { + return {}; +} std::string View::GetRequestBodyForLogging(const std::string& /*body*/) { return {}; } std::string View::GetResponseForLogging( const Response& /*response*/, const std::string& /*serialized_response*/, - USERVER_NAMESPACE::server::request::RequestContext& /*context*/ + RequestContext& /*context*/ ) { return {}; } diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/octetget/view.hpp b/chaotic-openapi/integration_tests/src/handlers/simple/octetget/view.hpp index fa5a9258cbe4..333cbdf6ee7f 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/octetget/view.hpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/octetget/view.hpp @@ -14,15 +14,16 @@ struct HandlerTag; class View final { public: using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; - static Response Handle(Request&& request, Deps&& deps); + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); static std::string GetRequestBodyForLogging(const std::string& body); static std::string GetResponseForLogging( const Response& response, const std::string& serialized_response, - USERVER_NAMESPACE::server::request::RequestContext& context + RequestContext& context ); }; diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/secretget/view.cpp b/chaotic-openapi/integration_tests/src/handlers/simple/secretget/view.cpp index 3918c1c2155f..5c6a03d1bc0d 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/secretget/view.cpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/secretget/view.cpp @@ -2,12 +2,18 @@ namespace handlers::simple::secretget { -Response View::Handle(Request&& /*request*/, Deps&& /*deps*/) { return {}; } +Response View::Handle( + Request&& /*request*/, + Deps&& /*deps*/, + RequestContext& /*context*/ +) { + return {}; +} std::string View::GetResponseForLogging( const Response& /*response*/, const std::string& /*serialized_response*/, - USERVER_NAMESPACE::server::request::RequestContext& /*context*/ + RequestContext& /*context*/ ) { return {}; } diff --git a/chaotic-openapi/integration_tests/src/handlers/simple/secretget/view.hpp b/chaotic-openapi/integration_tests/src/handlers/simple/secretget/view.hpp index 3b736082a5ae..cf60e3a37159 100644 --- a/chaotic-openapi/integration_tests/src/handlers/simple/secretget/view.hpp +++ b/chaotic-openapi/integration_tests/src/handlers/simple/secretget/view.hpp @@ -14,13 +14,14 @@ struct HandlerTag; class View final { public: using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; - static Response Handle(Request&& request, Deps&& deps); + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); static std::string GetResponseForLogging( const Response& response, const std::string& serialized_response, - USERVER_NAMESPACE::server::request::RequestContext& context + RequestContext& context ); }; diff --git a/chaotic-openapi/src/chaotic/openapi/server/handler_logging_test.cpp b/chaotic-openapi/src/chaotic/openapi/server/handler_logging_test.cpp index fef0ece7c9b2..0a2b5e5b0981 100644 --- a/chaotic-openapi/src/chaotic/openapi/server/handler_logging_test.cpp +++ b/chaotic-openapi/src/chaotic/openapi/server/handler_logging_test.cpp @@ -22,7 +22,7 @@ using FakeDeps = co_server::dependencies::ForHandler; // ---- MinimalView (no logging methods) ---- struct MinimalView { - static FakeResponse Handle(FakeRequest&&, FakeDeps&&) { return {}; } + static FakeResponse Handle(FakeRequest&&, FakeDeps&&, server::request::RequestContext&) { return {}; } }; static_assert(!co_server::impl::ViewHasGetRequestBodyForLoggingJson); @@ -40,7 +40,7 @@ TEST(HandlerLogging, MinimalViewReturnsNullopt) { // ---- JsonBodyView ---- struct JsonBodyView { - static FakeResponse Handle(FakeRequest&&, FakeDeps&&) { return {}; } + static FakeResponse Handle(FakeRequest&&, FakeDeps&&, server::request::RequestContext&) { return {}; } static std::string GetRequestBodyForLogging(const formats::json::Value& body) { return "k=" + body["k"].As(""); @@ -70,7 +70,7 @@ TEST(HandlerLogging, JsonBodyInvalidThrows) { // ---- StringBodyView ---- struct StringBodyView { - static FakeResponse Handle(FakeRequest&&, FakeDeps&&) { return {}; } + static FakeResponse Handle(FakeRequest&&, FakeDeps&&, server::request::RequestContext&) { return {}; } static std::string GetRequestBodyForLogging(const std::string& body) { return "len=" + std::to_string(body.size()); @@ -94,7 +94,7 @@ TEST(HandlerLogging, StringBody) { // ---- ResponseLoggingView ---- struct ResponseLoggingView { - static FakeResponse Handle(FakeRequest&&, FakeDeps&&) { return {}; } + static FakeResponse Handle(FakeRequest&&, FakeDeps&&, server::request::RequestContext&) { return {}; } static std::string GetResponseForLogging(const FakeResponse&, const std::string& serialized, server::request::RequestContext&) { diff --git a/cmake/ChaoticGen.cmake b/cmake/ChaoticGen.cmake index 37ffe0a06008..8ef67ba8b177 100644 --- a/cmake/ChaoticGen.cmake +++ b/cmake/ChaoticGen.cmake @@ -477,6 +477,7 @@ function(userver_generate_config_yaml BINARY_TARGET) VERBATIM ) add_custom_target("${BINARY_TARGET}_config" ALL DEPENDS "${PARSE_OUTPUT}") + add_dependencies("${BINARY_TARGET}" "${BINARY_TARGET}_config") endfunction() function(_userver_collect_extra_config_yamls_impl TARGET) diff --git a/samples/chaotic_openapi_service/CMakeLists.txt b/samples/chaotic_openapi_service/CMakeLists.txt index 1047bcf2c5e8..128797d9f1b6 100644 --- a/samples/chaotic_openapi_service/CMakeLists.txt +++ b/samples/chaotic_openapi_service/CMakeLists.txt @@ -7,7 +7,7 @@ find_package( REQUIRED ) -add_library(${PROJECT_NAME}_objs OBJECT src/say_hello.hpp src/say_hello.cpp src/hello_handler.hpp src/hello_handler.cpp) +add_library(${PROJECT_NAME}_objs OBJECT src/auth_bearer.hpp src/auth_bearer.cpp src/say_hello.hpp src/say_hello.cpp src/hello_handler.hpp src/hello_handler.cpp) target_link_libraries(${PROJECT_NAME}_objs userver::core) target_include_directories(${PROJECT_NAME}_objs PUBLIC src) @@ -34,6 +34,15 @@ userver_target_generate_openapi_handlers( SCHEMAS "${CMAKE_CURRENT_SOURCE_DIR}/handlers/insecure/openapi.yaml" ) target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}-handler-insecure_objs) + +userver_target_generate_openapi_handlers( + ${PROJECT_NAME}-handler-secure_objs + NAME secure + OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/handlers/secure" + SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src" + SCHEMAS "${CMAKE_CURRENT_SOURCE_DIR}/handlers/secure/openapi.yaml" +) +target_link_libraries(${PROJECT_NAME} ${PROJECT_NAME}-handler-secure_objs) # /// [chaotic-handler] # /// [generate-config] @@ -45,3 +54,4 @@ userver_generate_config_yaml( # /// [generate-config] userver_testsuite_add_simple(CONFIG_PATH "${CMAKE_CURRENT_BINARY_DIR}/config.yaml") + diff --git a/samples/chaotic_openapi_service/handlers/secure/openapi.yaml b/samples/chaotic_openapi_service/handlers/secure/openapi.yaml new file mode 100644 index 000000000000..857cb948de20 --- /dev/null +++ b/samples/chaotic_openapi_service/handlers/secure/openapi.yaml @@ -0,0 +1,25 @@ +openapi: 3.0.0 +info: + title: Secure handler + version: '1.0' +paths: + /secure/greeting: + get: + operationId: greetingGet + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GreetingResponse' +components: + schemas: + GreetingResponse: + type: object + additionalProperties: false + required: + - greeting + properties: + greeting: + type: string diff --git a/samples/chaotic_openapi_service/main.cpp b/samples/chaotic_openapi_service/main.cpp index 0f5afb7b854a..966330e2d198 100644 --- a/samples/chaotic_openapi_service/main.cpp +++ b/samples/chaotic_openapi_service/main.cpp @@ -1,10 +1,13 @@ #include #include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -13,8 +16,11 @@ #include #include +#include #include +#include "auth_bearer.hpp" + int main(int argc, char* argv[]) { auto component_list = USERVER_NAMESPACE::components::MinimalServerComponentList() @@ -22,6 +28,8 @@ int main(int argc, char* argv[]) { .Append() .Append() .Append() + .Append() + .Append() .AppendComponentList(USERVER_NAMESPACE::clients::http::ComponentList()) .Append() /// [register-qos] @@ -32,10 +40,15 @@ int main(int argc, char* argv[]) { .Append<::clients::test::Component>() /// [register-client] /// [register-handlers] - .AppendComponentList(::handlers::insecure::ChaoticHandlersList()); + .Append>() + .AppendComponentList(::handlers::insecure::ChaoticHandlersList()) + .AppendComponentList(::handlers::secure::ChaoticHandlersList()); /// [register-handlers] USERVER_NAMESPACE::chaotic::openapi::middlewares::AppendDefaultMiddlewares(component_list); + server::handlers::auth::RegisterAuthCheckerFactory(); + return USERVER_NAMESPACE::utils::DaemonMain(argc, argv, component_list); } diff --git a/samples/chaotic_openapi_service/src/auth_bearer.cpp b/samples/chaotic_openapi_service/src/auth_bearer.cpp new file mode 100644 index 000000000000..a98082676b37 --- /dev/null +++ b/samples/chaotic_openapi_service/src/auth_bearer.cpp @@ -0,0 +1,102 @@ +#include "auth_bearer.hpp" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace samples::auth { + +namespace { + +// Bearer tokens to user ids mapping from the 'tokens' section of the secdist config. +class AuthTokens final { +public: + explicit AuthTokens(const formats::json::Value& data) { + const auto tokens = data["tokens"]; + if (!tokens.IsObject()) { + return; + } + for (const auto& [token, user_id] : Items(tokens)) { + tokens_.emplace(token, user_id.As()); + } + } + + const std::unordered_map& Get() const { return tokens_; } + +private: + std::unordered_map tokens_; +}; + +class AuthCheckerBearer final : public server::handlers::auth::AuthCheckerBase { +public: + using AuthCheckResult = server::handlers::auth::AuthCheckResult; + + explicit AuthCheckerBearer(std::unordered_map tokens) : tokens_(std::move(tokens)) {} + + [[nodiscard]] AuthCheckResult CheckAuth( + const server::http::HttpRequest& request, + server::request::RequestContext& request_context + ) const override; + + [[nodiscard]] bool SupportsUserAuth() const noexcept override { return true; } + +private: + const std::unordered_map tokens_; +}; + +AuthCheckerBearer::AuthCheckResult AuthCheckerBearer::CheckAuth( + const server::http::HttpRequest& request, + server::request::RequestContext& request_context +) const { + const auto& auth_value = request.GetHeader(http::headers::kAuthorization); + constexpr std::string_view kBearerPrefix = "Bearer "; + if (!auth_value.starts_with(kBearerPrefix)) { + return AuthCheckResult{ + AuthCheckResult::Status::kTokenNotFound, + {}, + "Bearer token is required", + server::handlers::HandlerErrorCode::kUnauthorized, + }; + } + + const std::string_view token{auth_value.data() + kBearerPrefix.size(), auth_value.size() - kBearerPrefix.size()}; + const auto it = tokens_.find(std::string{token}); + if (it == tokens_.end()) { + return AuthCheckResult{ + AuthCheckResult::Status::kInvalidToken, + {}, + "Unknown bearer token", + server::handlers::HandlerErrorCode::kUnauthorized, + }; + } + + SetUserAuthInfo( + request_context, + server::auth::UserAuthInfo{ + server::auth::UserId{it->second}, + server::auth::UserEnv::kProd, + server::auth::UserProvider::kYandex, + } + ); + return {}; +} + +} // namespace + +CheckerFactory::CheckerFactory(const components::ComponentContext& context) + : tokens_(context.FindComponent().Get().Get().Get()) {} + +server::handlers::auth::AuthCheckerBasePtr +CheckerFactory::MakeAuthChecker(const server::handlers::auth::HandlerAuthConfig&) const { + return std::make_shared(tokens_); +} + +} // namespace samples::auth diff --git a/samples/chaotic_openapi_service/src/auth_bearer.hpp b/samples/chaotic_openapi_service/src/auth_bearer.hpp new file mode 100644 index 000000000000..b0d756213bcc --- /dev/null +++ b/samples/chaotic_openapi_service/src/auth_bearer.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include +#include +#include + +#include +#include + +namespace samples::auth { + +class CheckerFactory final : public server::handlers::auth::AuthCheckerFactoryBase { +public: + static constexpr std::string_view kAuthType = "bearer"; + + explicit CheckerFactory(const components::ComponentContext& context); + + server::handlers::auth::AuthCheckerBasePtr MakeAuthChecker( + const server::handlers::auth::HandlerAuthConfig& auth_config + ) const override; + +private: + std::unordered_map tokens_; +}; + +} // namespace samples::auth diff --git a/samples/chaotic_openapi_service/src/handlers/insecure/insecuresecretpost/view.cpp b/samples/chaotic_openapi_service/src/handlers/insecure/insecuresecretpost/view.cpp index 2e0afa40a122..0c05d611bb7e 100644 --- a/samples/chaotic_openapi_service/src/handlers/insecure/insecuresecretpost/view.cpp +++ b/samples/chaotic_openapi_service/src/handlers/insecure/insecuresecretpost/view.cpp @@ -7,7 +7,11 @@ namespace handlers::insecure::insecuresecretpost { /// [view-impl] -Response View::Handle(Request&& request, Deps&& /*deps*/) { +Response View::Handle( + Request&& request, + Deps&& /*deps*/, + RequestContext& /*context*/ +) { return Response200{.body = {.greeting = fmt::format("Hello, {}!", request.name)}}; } /// [view-impl] @@ -15,7 +19,7 @@ Response View::Handle(Request&& request, Deps&& /*deps*/) { std::string View::GetResponseForLogging( const Response& /*response*/, const std::string& /*serialized_response*/, - USERVER_NAMESPACE::server::request::RequestContext& /*context*/ + RequestContext& /*context*/ ) { return {}; } diff --git a/samples/chaotic_openapi_service/src/handlers/insecure/insecuresecretpost/view.hpp b/samples/chaotic_openapi_service/src/handlers/insecure/insecuresecretpost/view.hpp index 9959bcb23c84..5f15d02d4eba 100644 --- a/samples/chaotic_openapi_service/src/handlers/insecure/insecuresecretpost/view.hpp +++ b/samples/chaotic_openapi_service/src/handlers/insecure/insecuresecretpost/view.hpp @@ -14,13 +14,14 @@ struct HandlerTag; class View final { public: using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; - static Response Handle(Request&& request, Deps&& deps); + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); static std::string GetResponseForLogging( const Response& response, const std::string& serialized_response, - USERVER_NAMESPACE::server::request::RequestContext& context + RequestContext& context ); }; diff --git a/samples/chaotic_openapi_service/src/handlers/secure/greetingget/view.cpp b/samples/chaotic_openapi_service/src/handlers/secure/greetingget/view.cpp new file mode 100644 index 000000000000..c7c8a0fa7527 --- /dev/null +++ b/samples/chaotic_openapi_service/src/handlers/secure/greetingget/view.cpp @@ -0,0 +1,18 @@ +#include "view.hpp" + +#include + +#include +#include + +namespace handlers::secure::greetingget { + +Response View::Handle(Request&& /*request*/, Deps&& /*deps*/, RequestContext& context) { + const auto& auth_info = USERVER_NAMESPACE::server::auth::GetUserAuthInfo(context); + const auto user_id = auth_info.GetDefaultUserId(); + return Response200{ + .body = {.greeting = fmt::format("Hello, user {}!", USERVER_NAMESPACE::server::auth::ToUInt64(user_id))} + }; +} + +} // namespace handlers::secure::greetingget \ No newline at end of file diff --git a/samples/chaotic_openapi_service/src/handlers/secure/greetingget/view.hpp b/samples/chaotic_openapi_service/src/handlers/secure/greetingget/view.hpp new file mode 100644 index 000000000000..33419634f407 --- /dev/null +++ b/samples/chaotic_openapi_service/src/handlers/secure/greetingget/view.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include + +#include +#include +#include +#include + +namespace handlers::secure::greetingget { + +struct HandlerTag; + +class View final { +public: + using Deps = USERVER_NAMESPACE::chaotic::openapi::server::dependencies::ForHandler; + using RequestContext = USERVER_NAMESPACE::server::request::RequestContext; + + static Response Handle(Request&& request, Deps&& deps, RequestContext& context); +}; + +} // namespace handlers::secure::greetingget \ No newline at end of file diff --git a/samples/chaotic_openapi_service/src/ya.make b/samples/chaotic_openapi_service/src/ya.make index 6448583f61ac..9748d1645224 100644 --- a/samples/chaotic_openapi_service/src/ya.make +++ b/samples/chaotic_openapi_service/src/ya.make @@ -15,9 +15,11 @@ ADDINCL( ) SRCS( + auth_bearer.cpp hello_handler.cpp say_hello.cpp handlers/insecure/insecuresecretpost/view.cpp + handlers/secure/greetingget/view.cpp ) ADDINCL( @@ -92,13 +94,48 @@ RUN_PROGRAM( config.chaotic.yaml ) +RUN_PROGRAM( + taxi/uservices/userver/chaotic-openapi/bin + --name secure + --gen handlers + -o ${BINDIR}/handlers/secure + --clang-format '' + ../handlers/secure/openapi.yaml + OUTPUT_INCLUDES + ${CHAOTIC_INCLUDES} + ${CHAOTIC_OPENAPI_INCLUDES} + handlers/secure/greetingget/view.hpp + IN_NOPARSE + ../handlers/secure/openapi.yaml + OUT + include/handlers/secure/openapi.hpp + include/handlers/secure/openapi_fwd.hpp + include/handlers/secure/openapi_parsers.ipp + include/handlers/secure/openapi_sax_parsers.hpp + + src/handlers/secure/openapi.cpp + + include/handlers/secure/greetingget/handler.hpp + include/handlers/secure/chaotic_handlers_list.hpp + include/handlers/secure/greetingget/requests.hpp + include/handlers/secure/greetingget/responses.hpp + + src/handlers/secure/greetingget/handler.cpp + src/handlers/secure/greetingget/requests.cpp + src/handlers/secure/greetingget/responses.cpp + + config.chaotic.yaml +) + RUN_PROGRAM( taxi/uservices/userver/scripts/chaotic ${BINDIR}/config.chaotic.yaml + ${BINDIR}/handlers/secure/config.chaotic.yaml ${CURDIR}/../static_config.yaml -o ./config.yaml IN_NOPARSE ${BINDIR}/config.chaotic.yaml + ${BINDIR}/handlers/secure/config.chaotic.yaml ../static_config.yaml OUT config.yaml diff --git a/samples/chaotic_openapi_service/static_config.user.yaml b/samples/chaotic_openapi_service/static_config.user.yaml index d7164832cfc0..5cb94ccedf87 100644 --- a/samples/chaotic_openapi_service/static_config.user.yaml +++ b/samples/chaotic_openapi_service/static_config.user.yaml @@ -24,6 +24,10 @@ components_manager: dns-client: fs-task-processor: fs-task-processor + default-secdist-provider: # Component that loads secrets from secdist. + config: /etc/chaotic_openapi_service/secdist.json # Values are supposed to be stored in this file + missing-ok: true # ... but if the file is missing it is still ok + environment-secrets-key: SECDIST_CONFIG # ... values will be loaded from this environment value http-client: http-client-core: fs-task-processor: fs-task-processor @@ -40,6 +44,11 @@ components_manager: method: GET,POST # It will only reply to GET (HEAD) and POST requests. task_processor: main-task-processor # Run it on CPU bound task processor + handler-greeting-get: # Generated handler, overrides the config.chaotic.yaml fragment. + auth: # Authorization config for this handler + types: + - bearer # Authorization type that was registered in main() + dynamic-config: updates-enabled: true fs-task-processor: fs-task-processor diff --git a/samples/chaotic_openapi_service/testsuite/conftest.py b/samples/chaotic_openapi_service/testsuite/conftest.py index 55c869b40384..45264beed316 100644 --- a/samples/chaotic_openapi_service/testsuite/conftest.py +++ b/samples/chaotic_openapi_service/testsuite/conftest.py @@ -1,3 +1,5 @@ +import json + import pytest pytest_plugins = ['pytest_userver.plugins.core'] @@ -14,3 +16,14 @@ def do_patch(config_yaml, config_vars): return do_patch # /// [URL] + + +@pytest.fixture(scope='session') +def service_env(): + secdist_config = { + 'tokens': { + 'user-1-token': 123, + }, + } + + return {'SECDIST_CONFIG': json.dumps(secdist_config)} diff --git a/samples/chaotic_openapi_service/testsuite/test_auth.py b/samples/chaotic_openapi_service/testsuite/test_auth.py new file mode 100644 index 000000000000..22c01cbab894 --- /dev/null +++ b/samples/chaotic_openapi_service/testsuite/test_auth.py @@ -0,0 +1,19 @@ +async def test_greeting_requires_auth(service_client): + response = await service_client.get('/secure/greeting') + assert response.status == 401 + + +async def test_greeting_with_bad_token(service_client): + response = await service_client.get('/secure/greeting', headers={'Authorization': 'not a bearer token'}) + assert response.status == 401 + + +async def test_greeting_with_unknown_token(service_client): + response = await service_client.get('/secure/greeting', headers={'Authorization': 'Bearer unknown-token'}) + assert response.status == 401 + + +async def test_greeting_with_auth(service_client): + response = await service_client.get('/secure/greeting', headers={'Authorization': 'Bearer user-1-token'}) + assert response.status == 200 + assert response.json()['greeting'] == 'Hello, user 123!'