From 1cddf7330129e1f4aab3dda0bb906fbb91357384 Mon Sep 17 00:00:00 2001 From: Totto16 Date: Wed, 23 Oct 2024 01:44:39 +0200 Subject: [PATCH 1/9] build: add fallback for cpp-httplib, a c++ curl wrapper --- subprojects/cpr.wrap | 13 ++++++++++ subprojects/curl.wrap | 13 ++++++++++ tools/dependencies/meson.build | 44 ++++++++++++++++------------------ 3 files changed, 47 insertions(+), 23 deletions(-) create mode 100644 subprojects/cpr.wrap create mode 100644 subprojects/curl.wrap diff --git a/subprojects/cpr.wrap b/subprojects/cpr.wrap new file mode 100644 index 00000000..601df204 --- /dev/null +++ b/subprojects/cpr.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = cpr-1.10.5 +source_url = https://github.com/libcpr/cpr/archive/1.10.5.tar.gz +source_filename = cpr-1.10.5.tar.gz +source_hash = c8590568996cea918d7cf7ec6845d954b9b95ab2c4980b365f582a665dea08d8 +patch_filename = cpr_1.10.5-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/cpr_1.10.5-1/get_patch +patch_hash = 01e31e1bd47bc55dabc8e3b0633451abefc37532ba57b3ba3f0a304592ea5ac5 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/cpr_1.10.5-1/cpr-1.10.5.tar.gz +wrapdb_version = 1.10.5-1 + +[provide] +cpr = cpr_dep diff --git a/subprojects/curl.wrap b/subprojects/curl.wrap new file mode 100644 index 00000000..f7e384b8 --- /dev/null +++ b/subprojects/curl.wrap @@ -0,0 +1,13 @@ +[wrap-file] +directory = curl-8.10.1 +source_url = https://github.com/curl/curl/releases/download/curl-8_10_1/curl-8.10.1.tar.xz +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/curl_8.10.1-1/curl-8.10.1.tar.xz +source_filename = curl-8.10.1.tar.xz +source_hash = 73a4b0e99596a09fa5924a4fb7e4b995a85fda0d18a2c02ab9cf134bebce04ee +patch_filename = curl_8.10.1-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/curl_8.10.1-1/get_patch +patch_hash = 707c28f35fc9b0e8d68c0c2800712007612f922a31da9637ce706a2159f3ddd8 +wrapdb_version = 8.10.1-1 + +[provide] +dependency_names = libcurl diff --git a/tools/dependencies/meson.build b/tools/dependencies/meson.build index c115da32..5ce100ed 100644 --- a/tools/dependencies/meson.build +++ b/tools/dependencies/meson.build @@ -229,37 +229,35 @@ if build_application } endif - online_multiplayer_supported = true - - if ( - meson.is_cross_build() - and ( - host_machine.system() == 'switch' - or host_machine.system() == '3ds' - ) + cpp_httlib_dep = dependency( + 'cpp-httplib', + required: false, + default_options: { + 'cpp-httplib_openssl': 'enabled', + 'cpp-httplib_zlib': 'enabled', + }, ) - online_multiplayer_supported = false - # TODO: use libcurl and - # https://github.com/uctakeoff/uc-curl - # or https://github.com/JosephP91/curlcpp + if cpp_httlib_dep.found() + + graphics_lib += {'deps': [graphics_lib.get('deps'), cpp_httlib_dep]} + + else + + curl_cpp_wrapper = dependency( + 'cpr', + required: true, + default_options: {'tests': 'disabled'}, + ) graphics_lib += { + 'deps': [graphics_lib.get('deps'), curl_cpp_wrapper], 'compile_args': [ graphics_lib.get('compile_args'), - '-D_ONLINE_MULTIPLAYER_NOT_SUPPORTED', + '-D_OOPETRIS_ONLINE_USE_CURL', ], } - else - cpp_httlib_dep = dependency( - 'cpp-httplib', - required: true, - default_options: { - 'cpp-httplib_openssl': 'enabled', - 'cpp-httplib_zlib': 'enabled', - }, - ) - graphics_lib += {'deps': [graphics_lib.get('deps'), cpp_httlib_dep]} + endif build_installer = get_option('build_installer') From 4a9c552edf6ce5386b2f3597f349d2ad5a9b3875 Mon Sep 17 00:00:00 2001 From: Totto16 Date: Wed, 23 Oct 2024 19:54:40 +0200 Subject: [PATCH 2/9] feat: add generic interface for the http client separate API and client, make it possible to use multiple backends implement cpp-httplib backend --- src/helper/graphic_utils.cpp | 2 - src/lobby/api.cpp | 229 +++++------------- src/lobby/api.hpp | 50 +--- src/lobby/client.cpp | 94 +++++++ src/lobby/client.hpp | 92 +++++++ src/lobby/constants.hpp | 6 + src/lobby/curl_client.cpp | 2 + src/lobby/curl_client.hpp | 2 + src/lobby/httplib_client.cpp | 107 ++++++++ src/lobby/httplib_client.hpp | 82 +++++++ src/lobby/meson.build | 21 +- src/meson.build | 5 +- src/scenes/meson.build | 5 +- .../multiplayer_menu/multiplayer_menu.cpp | 7 +- src/scenes/online_lobby/online_lobby.cpp | 9 +- src/scenes/online_lobby/online_lobby.hpp | 2 +- src/scenes/scene.cpp | 10 +- tools/dependencies/meson.build | 5 + 18 files changed, 494 insertions(+), 236 deletions(-) create mode 100644 src/lobby/client.cpp create mode 100644 src/lobby/client.hpp create mode 100644 src/lobby/constants.hpp create mode 100644 src/lobby/curl_client.cpp create mode 100644 src/lobby/curl_client.hpp create mode 100644 src/lobby/httplib_client.cpp create mode 100644 src/lobby/httplib_client.hpp diff --git a/src/helper/graphic_utils.cpp b/src/helper/graphic_utils.cpp index d387f099..d25bb41e 100644 --- a/src/helper/graphic_utils.cpp +++ b/src/helper/graphic_utils.cpp @@ -11,9 +11,7 @@ std::vector utils::supported_features() { std::vector features{}; -#if !defined(_ONLINE_MULTIPLAYER_NOT_SUPPORTED) features.emplace_back("online multiplayer"); -#endif #if defined(_HAVE_FILE_DIALOGS) features.emplace_back("file dialogs"); diff --git a/src/lobby/api.cpp b/src/lobby/api.cpp index 27df24dd..f41880df 100644 --- a/src/lobby/api.cpp +++ b/src/lobby/api.cpp @@ -2,109 +2,17 @@ #include "api.hpp" +#include -namespace { - - inline helper::expected is_json_response(const httplib::Result& result) { - if (not result->has_header("Content-Type")) { - return helper::unexpected{ "Content-Type not set!" }; - } - - if (const auto value = result->get_header_value("Content-Type"); value != constants::json_content_type) { - return helper::unexpected{ fmt::format("Content-Type is not json but {}", value) }; - } - - return result->body; - } - - - inline helper::expected is_error_message_response(const httplib::Result& result - ) { - - const auto body = is_json_response(result); - if (not body.has_value()) { - return helper::unexpected{ body.error() }; - } - - const auto parsed = json::try_parse_json(body.value()); - - if (parsed.has_value()) { - return parsed.value(); - } - - return helper::unexpected{ fmt::format("Couldn't parse json with error: {}", parsed.error()) }; - } - - inline helper::expected is_request_ok(const httplib::Result& result, int ok_code = 200) { - - if (not result) { - return helper::unexpected{ - fmt::format("Request failed with: {}", httplib::to_string(result.error())) - }; - } - - if (result->status == 401) { - - const auto error_type = is_error_message_response(result); - - if (error_type.has_value()) { - return helper::unexpected{ fmt::format("Unauthorized: {}", error_type.value().message) }; - } - - return helper::unexpected{ "Unauthorized" }; - } - - - if (result->status != ok_code) { - - const auto error_type = is_error_message_response(result); - - if (error_type.has_value()) { - return helper::unexpected{ fmt::format( - "Got error response with status code {}: '{}' and message: {}", result->status, - httplib::status_message(result->status), error_type.value().message - ) }; - } - - - return helper::unexpected{ fmt::format( - "Got error response with status code {}: '{}' but expected {}", result->status, - httplib::status_message(result->status), ok_code - ) }; - } - - return {}; - }; - - - template - helper::expected get_json_from_request(const httplib::Result& result, int ok_code = 200) { - - const auto temp = is_request_ok(result, ok_code); - if (not temp.has_value()) { - return helper::unexpected{ temp.error() }; - } - - const auto body = is_json_response(result); - if (not body.has_value()) { - return helper::unexpected{ body.error() }; - } - - const auto parsed = json::try_parse_json(body.value()); - - if (parsed.has_value()) { - return parsed.value(); - } - - return helper::unexpected{ fmt::format("Couldn't parse json with error: {}", parsed.error()) }; - } - - -} // namespace +#if defined(_OOPETRIS_ONLINE_USE_CURL) +#include "./curl_client.hpp" +#else +#include "./httplib_client.hpp" +#endif -helper::expected lobby::Client::check_compatibility() { +helper::expected lobby::API::check_compatibility() { const auto server_version = get_version(); if (not server_version.has_value()) { @@ -116,74 +24,48 @@ helper::expected lobby::Client::check_compatibility() { const auto& version = server_version.value(); //TODO(Totto): if version is semver, support semver comparison - if (Client::supported_version.string() != version.version) { + if (API::supported_version.string() != version.version) { return helper::unexpected{ fmt::format( "Connecting to unsupported server, version is {}, but we support only {}", - Client::supported_version.string(), version.version + API::supported_version.string(), version.version ) }; } return {}; } -helper::expected lobby::Client::check_reachability() { +helper::expected lobby::API::check_reachability() { - auto result = m_client.Get("/"); + auto result = m_client->Get("/"); - if (not result) { - return helper::unexpected{ - fmt::format("Server not reachable: {}", httplib::to_string(result.error())) - }; + if (auto error = result->get_error(); error.has_value()) { + return helper::unexpected{ fmt::format("Server not reachable: {}", error.value()) }; } return {}; } -lobby::Client::Client(const std::string& api_url) : m_client{ api_url } { +lobby::API::API(const std::string& api_url) + : m_client{ std::make_unique(api_url) } { } - // clang-format off - m_client.set_default_headers({ -#if defined(CPPHTTPLIB_ZLIB_SUPPORT) || defined(CPPHTTPLIB_BROTLI_SUPPORT) - { "Accept-Encoding", - -#if defined(CPPHTTPLIB_ZLIB_SUPPORT) - "gzip, deflate" -#endif -#if defined(CPPHTTPLIB_ZLIB_SUPPORT) && defined(CPPHTTPLIB_BROTLI_SUPPORT) - ", " -#endif -#if defined(CPPHTTPLIB_BROTLI_SUPPORT) - "br" -#endif - }, -#endif - // clang-format on - { "Accept", constants::json_content_type } }); - -#if defined(CPPHTTPLIB_ZLIB_SUPPORT) || defined(CPPHTTPLIB_BROTLI_SUPPORT) - m_client.set_compress(true); - m_client.set_decompress(true); -#endif -} - -helper::expected lobby::Client::get_version() { - auto res = m_client.Get("/version"); +helper::expected lobby::API::get_version() { + auto res = m_client->Get("/version"); return get_json_from_request(res); } -lobby::Client::Client(Client&& other) noexcept +lobby::API::API(API&& other) noexcept : m_client{ std::move(other.m_client) }, m_authentication_token{ std::move(other.m_authentication_token) } { } -lobby::Client::~Client() = default; +lobby::API::~API() = default; -helper::expected lobby::Client::get_client(const std::string& url) { +helper::expected lobby::API::get_api(const std::string& url) { - Client client{ url }; + API api{ url }; - const auto reachable = client.check_reachability(); + const auto reachable = api.check_reachability(); if (not reachable.has_value()) { return helper::unexpected{ reachable.error() }; @@ -191,27 +73,31 @@ helper::expected lobby::Client::get_client(const std //TODO(Totto): once version is standard, check here if the version is supported - return client; + return api; } -helper::expected lobby::Client::login(const Credentials& credentials) { - const auto json_result = json::try_json_to_string(credentials); +helper::expected lobby::API::login(const Credentials& credentials) { + auto json_result = json::try_json_to_string(credentials); if (not json_result.has_value()) { return helper::unexpected{ json_result.error() }; } - auto res = m_client.Post("/login", json_result.value(), constants::json_content_type); + auto payload = std::make_pair( + std::move(json_result.value()), ::http::constants::json_content_type + ); + + auto res = m_client->Post("/login", payload); return get_json_from_request(res); } -bool lobby::Client::is_authenticated() { +bool lobby::API::is_authenticated() { return m_authentication_token.has_value(); } -bool lobby::Client::authenticate(const Credentials& credentials) { +bool lobby::API::authenticate(const Credentials& credentials) { const auto result = login(credentials); @@ -223,19 +109,19 @@ bool lobby::Client::authenticate(const Credentials& credentials) { m_authentication_token = result.value().jwt; - m_client.set_bearer_token_auth(m_authentication_token.value()); + m_client->SetBearerAuth(m_authentication_token.value()); return true; } -helper::expected, std::string> lobby::Client::get_lobbies() { - auto res = m_client.Get("/lobbies"); +helper::expected, std::string> lobby::API::get_lobbies() { + auto res = m_client->Get("/lobbies"); return get_json_from_request>(res); } -helper::expected lobby::Client::join_lobby(int lobby_id) { +helper::expected lobby::API::join_lobby(int lobby_id) { if (not is_authenticated()) { return helper::unexpected{ "Authentication needed for this " @@ -243,12 +129,12 @@ helper::expected lobby::Client::join_lobby(int lobby_id) { }; } - auto res = m_client.Post(fmt::format("/lobbies/{}", lobby_id)); + auto res = m_client->Post(fmt::format("/lobbies/{}", lobby_id)); return is_request_ok(res, 204); } -helper::expected lobby::Client::get_lobby_detail(int lobby_id) { +helper::expected lobby::API::get_lobby_detail(int lobby_id) { if (not is_authenticated()) { return helper::unexpected{ "Authentication needed for this " @@ -256,12 +142,12 @@ helper::expected lobby::Client::get_lobby_detai }; } - auto res = m_client.Get(fmt::format("/lobbies/{}", lobby_id)); + auto res = m_client->Get(fmt::format("/lobbies/{}", lobby_id)); return get_json_from_request(res); } -helper::expected lobby::Client::delete_lobby(int lobby_id) { +helper::expected lobby::API::delete_lobby(int lobby_id) { if (not is_authenticated()) { return helper::unexpected{ "Authentication needed for this " @@ -269,12 +155,12 @@ helper::expected lobby::Client::delete_lobby(int lobby_id) { }; } - auto res = m_client.Delete(fmt::format("/lobbies/{}", lobby_id)); + auto res = m_client->Delete(fmt::format("/lobbies/{}", lobby_id)); return is_request_ok(res, 204); } -helper::expected lobby::Client::leave_lobby(int lobby_id) { +helper::expected lobby::API::leave_lobby(int lobby_id) { if (not is_authenticated()) { return helper::unexpected{ "Authentication needed for this " @@ -282,12 +168,12 @@ helper::expected lobby::Client::leave_lobby(int lobby_id) { }; } - auto res = m_client.Put(fmt::format("/lobbies/{}/leave", lobby_id)); + auto res = m_client->Put(fmt::format("/lobbies/{}/leave", lobby_id)); return is_request_ok(res, 204); } -helper::expected lobby::Client::start_lobby(int lobby_id) { +helper::expected lobby::API::start_lobby(int lobby_id) { if (not is_authenticated()) { return helper::unexpected{ "Authentication needed for this " @@ -295,13 +181,12 @@ helper::expected lobby::Client::start_lobby(int lobby_id) { }; } - auto res = m_client.Post(fmt::format("/lobbies/{}/start", lobby_id)); + auto res = m_client->Post(fmt::format("/lobbies/{}/start", lobby_id)); return is_request_ok(res, 204); } -helper::expected lobby::Client::create_lobby( - const CreateLobbyRequest& arguments +helper::expected lobby::API::create_lobby(const CreateLobbyRequest& arguments ) { if (not is_authenticated()) { return helper::unexpected{ @@ -310,30 +195,38 @@ helper::expected lobby::Client::create_ }; } - const auto json_result = json::try_json_to_string(arguments); + auto json_result = json::try_json_to_string(arguments); if (not json_result.has_value()) { return helper::unexpected{ json_result.error() }; } - auto res = m_client.Post("/lobbies", json_result.value(), constants::json_content_type); + auto payload = std::make_pair( + std::move(json_result.value()), ::http::constants::json_content_type + ); + + auto res = m_client->Post("/lobbies", payload); return get_json_from_request(res, 201); } -helper::expected, std::string> lobby::Client::get_users() { +helper::expected, std::string> lobby::API::get_users() { - auto res = m_client.Get("/users"); + auto res = m_client->Get("/users"); return get_json_from_request>(res); } -helper::expected lobby::Client::register_user(const RegisterRequest& register_request) { - const auto json_result = json::try_json_to_string(register_request); +helper::expected lobby::API::register_user(const RegisterRequest& register_request) { + auto json_result = json::try_json_to_string(register_request); if (not json_result.has_value()) { return helper::unexpected{ json_result.error() }; } - auto res = m_client.Post("/register", json_result.value(), constants::json_content_type); + auto payload = std::make_pair( + std::move(json_result.value()), ::http::constants::json_content_type + ); + + auto res = m_client->Post("/register", payload); return is_request_ok(res, 204); } diff --git a/src/lobby/api.hpp b/src/lobby/api.hpp index eca63d03..80ba02ba 100644 --- a/src/lobby/api.hpp +++ b/src/lobby/api.hpp @@ -2,45 +2,19 @@ #pragma once +#include "./client.hpp" -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wold-style-cast" -#pragma GCC diagnostic ignored "-Warray-bounds" -#pragma GCC diagnostic ignored "-Wunused-parameter" -#elif defined(_MSC_VER) -#pragma warning(disable : 4100) -#endif - -#define CPPHTTPLIB_USE_POLL // NOLINT(cppcoreguidelines-macro-usage) - -#include - -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#elif defined(_MSC_VER) -#pragma warning(default : 4100) -#endif - -#include -#include -#include - +#include "./types.hpp" #include "helper/windows.hpp" -#include "lobby/types.hpp" -#include -#include -namespace constants { - const constexpr auto json_content_type = "application/json"; -} +#include namespace lobby { - struct Client { + struct API { private: - httplib::Client m_client; + std::unique_ptr m_client; std::optional m_authentication_token; // lobby commit used: https://github.com/OpenBrickProtocolFoundation/lobby/commit/2e0c8d05592f4e4d08437e6cb754a30f02c4e97c @@ -50,7 +24,7 @@ namespace lobby { [[nodiscard]] helper::expected check_reachability(); - explicit Client(const std::string& api_url); + explicit API(const std::string& api_url); helper::expected get_version(); @@ -58,16 +32,16 @@ namespace lobby { public: - OOPETRIS_GRAPHICS_EXPORTED Client(Client&& other) noexcept; - OOPETRIS_GRAPHICS_EXPORTED Client& operator=(Client&& other) noexcept = delete; + OOPETRIS_GRAPHICS_EXPORTED API(API&& other) noexcept; + OOPETRIS_GRAPHICS_EXPORTED API& operator=(API&& other) noexcept = delete; - OOPETRIS_GRAPHICS_EXPORTED Client(const Client& other) = delete; - OOPETRIS_GRAPHICS_EXPORTED Client& operator=(const Client& other) = delete; + OOPETRIS_GRAPHICS_EXPORTED API(const API& other) = delete; + OOPETRIS_GRAPHICS_EXPORTED API& operator=(const API& other) = delete; - OOPETRIS_GRAPHICS_EXPORTED ~Client(); + OOPETRIS_GRAPHICS_EXPORTED ~API(); OOPETRIS_GRAPHICS_EXPORTED - [[nodiscard]] helper::expected static get_client(const std::string& url); + [[nodiscard]] helper::expected static get_api(const std::string& url); OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] bool is_authenticated(); diff --git a/src/lobby/client.cpp b/src/lobby/client.cpp new file mode 100644 index 00000000..9a9b9841 --- /dev/null +++ b/src/lobby/client.cpp @@ -0,0 +1,94 @@ + + +#include "./client.hpp" + + +#if defined(_OOPETRIS_ONLINE_USE_CURL) +#include "./curl_client.hpp" +#error "TODO" +#else + +#include "./httplib_client.hpp" + +std::string oopetris::http::status_message(int status) { + return httplib::status_message(status); +} + +#endif + +oopetris::http::Result::~Result() = default; + +oopetris::http::Client::~Client() = default; + +helper::expected oopetris::http::is_json_response( + const std::unique_ptr& result +) { + const auto content_type = result->get_header("Content-Type"); + if (not content_type.has_value()) { + return helper::unexpected{ "Content-Type not set!" }; + } + + if (content_type.value() != ::http::constants::json_content_type) { + return helper::unexpected{ fmt::format("Content-Type is not json but {}", content_type.value()) }; + } + + return result->body(); +} + +helper::expected oopetris::http::is_error_message_response( + const std::unique_ptr& result +) { + + const auto body = is_json_response(result); + if (not body.has_value()) { + return helper::unexpected{ body.error() }; + } + + const auto parsed = json::try_parse_json(body.value()); + + if (parsed.has_value()) { + return parsed.value(); + } + + return helper::unexpected{ fmt::format("Couldn't parse json with error: {}", parsed.error()) }; +} + +helper::expected +oopetris::http::is_request_ok(const std::unique_ptr& result, int ok_code) { + + if (auto error = result->get_error(); error.has_value()) { + return helper::unexpected{ fmt::format("Request failed with: {}", error.value()) }; + } + + if (result->status() == 401) { + + const auto error_type = is_error_message_response(result); + + if (error_type.has_value()) { + return helper::unexpected{ fmt::format("Unauthorized: {}", error_type.value().message) }; + } + + return helper::unexpected{ "Unauthorized" }; + } + + + if (result->status() != ok_code) { + + const auto error_type = is_error_message_response(result); + + if (error_type.has_value()) { + return helper::unexpected{ fmt::format( + "Got error response with status code {}: '{}' and message: {}", result->status(), + oopetris::http::status_message(result->status()), error_type.value().message + ) }; + } + + + return helper::unexpected{ fmt::format( + "Got error response with status code {}: '{}' but expected {}", result->status(), + oopetris::http::status_message(result->status()), ok_code + ) }; + } + + return {}; +}; diff --git a/src/lobby/client.hpp b/src/lobby/client.hpp new file mode 100644 index 00000000..a255a25b --- /dev/null +++ b/src/lobby/client.hpp @@ -0,0 +1,92 @@ + +#pragma once + + +#include "./constants.hpp" +#include "./types.hpp" +#include "helper/windows.hpp" + +#include +#include +#include +#include + + +#include + + +namespace oopetris::http { + + struct Result { + OOPETRIS_GRAPHICS_EXPORTED virtual ~Result(); + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::optional get_header(const std::string& key + ) const = 0; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::string body() const = 0; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual int status() const = 0; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::optional get_error() const = 0; + }; + + struct Client { + OOPETRIS_GRAPHICS_EXPORTED virtual ~Client(); + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr Get(const std::string& url) = 0; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr Delete(const std::string& url) = 0; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr Post( + const std::string& url, + const std::optional>& payload = std::nullopt + ) = 0; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr Put( + const std::string& url, + const std::optional>& payload = std::nullopt + ) = 0; + + OOPETRIS_GRAPHICS_EXPORTED virtual void SetBearerAuth(const std::string& token) = 0; + }; + + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::string status_message(int status); + + OOPETRIS_GRAPHICS_EXPORTED helper::expected is_json_response( + const std::unique_ptr& result + ); + + + OOPETRIS_GRAPHICS_EXPORTED helper::expected is_error_message_response( + const std::unique_ptr& result + ); + + OOPETRIS_GRAPHICS_EXPORTED helper::expected + is_request_ok(const std::unique_ptr& result, int ok_code = 200); + + template + helper::expected + get_json_from_request(const std::unique_ptr& result, int ok_code = 200) { + + const auto temp = is_request_ok(result, ok_code); + if (not temp.has_value()) { + return helper::unexpected{ temp.error() }; + } + + const auto body = is_json_response(result); + if (not body.has_value()) { + return helper::unexpected{ body.error() }; + } + + const auto parsed = json::try_parse_json(body.value()); + + if (parsed.has_value()) { + return parsed.value(); + } + + return helper::unexpected{ fmt::format("Couldn't parse json with error: {}", parsed.error()) }; + } + + +} // namespace oopetris::http diff --git a/src/lobby/constants.hpp b/src/lobby/constants.hpp new file mode 100644 index 00000000..7d4f9b6c --- /dev/null +++ b/src/lobby/constants.hpp @@ -0,0 +1,6 @@ + +#pragma once + +namespace http::constants { + const constexpr auto json_content_type = "application/json"; +} diff --git a/src/lobby/curl_client.cpp b/src/lobby/curl_client.cpp new file mode 100644 index 00000000..fe54bed5 --- /dev/null +++ b/src/lobby/curl_client.cpp @@ -0,0 +1,2 @@ + +#include "./curl_client.hpp" diff --git a/src/lobby/curl_client.hpp b/src/lobby/curl_client.hpp new file mode 100644 index 00000000..99ddf32d --- /dev/null +++ b/src/lobby/curl_client.hpp @@ -0,0 +1,2 @@ + +#pragma once diff --git a/src/lobby/httplib_client.cpp b/src/lobby/httplib_client.cpp new file mode 100644 index 00000000..e1461f01 --- /dev/null +++ b/src/lobby/httplib_client.cpp @@ -0,0 +1,107 @@ + +#include "./httplib_client.hpp" + + +#define TRANSFORM_RESULT(result) std::make_unique((result)) + + +namespace oopetris::http::implementation { + + + ActualResult::ActualResult(httplib::Result&& result) : m_result{ std::move(result) } { } + + ActualResult::~ActualResult() = default; + + [[nodiscard]] std::optional ActualResult::get_header(const std::string& key) const { + if (m_result->has_header(key)) { + return std::nullopt; + } + + return m_result->get_header_value(key); + } + + [[nodiscard]] std::string ActualResult::body() const { + return m_result->body; + } + + [[nodiscard]] int ActualResult::status() const { + return m_result->status; + } + + [[nodiscard]] std::optional ActualResult::get_error() const { + + if (not m_result) { + return httplib::to_string(m_result.error()); + } + + return std::nullopt; + } + + + ActualClient::ActualClient(ActualClient&& other) noexcept : m_client{ std::move(other.m_client) } { } + + ActualClient::~ActualClient() = default; + + ActualClient::ActualClient(const std::string& api_url) : m_client{ api_url } { + // clang-format off + m_client.set_default_headers({ +#if defined(CPPHTTPLIB_ZLIB_SUPPORT) || defined(CPPHTTPLIB_BROTLI_SUPPORT) + { "Accept-Encoding", + +#if defined(CPPHTTPLIB_ZLIB_SUPPORT) + "gzip, deflate" +#endif +#if defined(CPPHTTPLIB_ZLIB_SUPPORT) && defined(CPPHTTPLIB_BROTLI_SUPPORT) + ", " +#endif +#if defined(CPPHTTPLIB_BROTLI_SUPPORT) + "br" +#endif + }, +#endif + // clang-format on + { "Accept", ::http::constants::json_content_type } }); + +#if defined(CPPHTTPLIB_ZLIB_SUPPORT) || defined(CPPHTTPLIB_BROTLI_SUPPORT) + m_client.set_compress(true); + m_client.set_decompress(true); +#endif + } + + [[nodiscard]] std::unique_ptr ActualClient::Get(const std::string& url) { + return TRANSFORM_RESULT(m_client.Get(url)); + } + + [[nodiscard]] std::unique_ptr ActualClient::Delete(const std::string& url) { + return TRANSFORM_RESULT(m_client.Delete(url)); + } + + [[nodiscard]] std::unique_ptr + ActualClient::Post(const std::string& url, const std::optional>& payload) { + + if (not payload.has_value()) { + return TRANSFORM_RESULT(m_client.Post(url)); + } + + auto [content, content_type] = payload.value(); + + return TRANSFORM_RESULT(m_client.Post(url, content, content_type)); + } + + [[nodiscard]] std::unique_ptr + ActualClient::Put(const std::string& url, const std::optional>& payload) { + + if (not payload.has_value()) { + return TRANSFORM_RESULT(m_client.Put(url)); + } + + auto [content, content_type] = payload.value(); + + return TRANSFORM_RESULT(m_client.Put(url, content, content_type)); + } + + void ActualClient::SetBearerAuth(const std::string& token) { + + m_client.set_bearer_token_auth(token); + } +} // namespace oopetris::http::implementation diff --git a/src/lobby/httplib_client.hpp b/src/lobby/httplib_client.hpp new file mode 100644 index 00000000..9202e31d --- /dev/null +++ b/src/lobby/httplib_client.hpp @@ -0,0 +1,82 @@ + +#pragma once + +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" +#pragma GCC diagnostic ignored "-Warray-bounds" +#pragma GCC diagnostic ignored "-Wunused-parameter" +#elif defined(_MSC_VER) +#pragma warning(disable : 4100) +#endif + +#define CPPHTTPLIB_USE_POLL // NOLINT(cppcoreguidelines-macro-usage) + +#include + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) +#pragma warning(default : 4100) +#endif + + +#include "./client.hpp" + + +namespace oopetris::http::implementation { + + struct ActualResult : ::oopetris::http::Result { + private: + httplib::Result m_result; + + public: + OOPETRIS_GRAPHICS_EXPORTED ActualResult(httplib::Result&& result); + + OOPETRIS_GRAPHICS_EXPORTED ~ActualResult() override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::optional get_header(const std::string& key + ) const override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::string body() const override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] int status() const override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::optional get_error() const override; + }; + + + struct ActualClient : ::oopetris::http::Client { + private: + httplib::Client m_client; + + public: + OOPETRIS_GRAPHICS_EXPORTED ActualClient(ActualClient&& other) noexcept; + OOPETRIS_GRAPHICS_EXPORTED ActualClient& operator=(ActualClient&& other) noexcept = delete; + + OOPETRIS_GRAPHICS_EXPORTED ActualClient(const ActualClient& other) = delete; + OOPETRIS_GRAPHICS_EXPORTED ActualClient& operator=(const ActualClient& other) = delete; + + OOPETRIS_GRAPHICS_EXPORTED ~ActualClient() override; + + OOPETRIS_GRAPHICS_EXPORTED explicit ActualClient(const std::string& api_url); + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Get(const std::string& url) override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Delete(const std::string& url) override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Post( + const std::string& url, + const std::optional>& payload = std::nullopt + ) override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Put( + const std::string& url, + const std::optional>& payload = std::nullopt + ) override; + + OOPETRIS_GRAPHICS_EXPORTED void SetBearerAuth(const std::string& token) override; + }; + + +} // namespace oopetris::http::implementation diff --git a/src/lobby/meson.build b/src/lobby/meson.build index 6bf0b698..e8632334 100644 --- a/src/lobby/meson.build +++ b/src/lobby/meson.build @@ -1 +1,20 @@ -graphics_src_files += files('api.cpp', 'api.hpp', 'types.hpp') +if online_multiplayer_user_fallback + graphics_src_files += files( + 'curl_client.cpp', + 'curl_client.hpp', + ) +else + graphics_src_files += files( + 'httplib_client.cpp', + 'httplib_client.hpp', + ) +endif + +graphics_src_files += files( + 'api.cpp', + 'api.hpp', + 'client.cpp', + 'client.hpp', + 'constants.hpp', + 'types.hpp', +) diff --git a/src/meson.build b/src/meson.build index 75d0d473..f3f4571a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -11,10 +11,7 @@ if build_application subdir('manager') subdir('scenes') subdir('ui') - - if online_multiplayer_supported - subdir('lobby') - endif + subdir('lobby') if have_discord_sdk subdir('discord') diff --git a/src/scenes/meson.build b/src/scenes/meson.build index daf05632..80bbad87 100644 --- a/src/scenes/meson.build +++ b/src/scenes/meson.build @@ -10,7 +10,4 @@ subdir('recording_selector') subdir('replay_game') subdir('settings_menu') subdir('single_player_game') - -if online_multiplayer_supported - subdir('online_lobby') -endif +subdir('online_lobby') diff --git a/src/scenes/multiplayer_menu/multiplayer_menu.cpp b/src/scenes/multiplayer_menu/multiplayer_menu.cpp index c4852bde..4f32bd2b 100644 --- a/src/scenes/multiplayer_menu/multiplayer_menu.cpp +++ b/src/scenes/multiplayer_menu/multiplayer_menu.cpp @@ -43,7 +43,7 @@ namespace scenes { ); m_main_grid.get(local_button_id)->disable(); - const auto online_button_id = m_main_grid.add( + m_main_grid.add( service_provider, "Online", service_provider->font_manager().get(FontId::Default), Color::white(), focus_helper.focus_id(), [this](const ui::TextButton&) -> bool { @@ -52,11 +52,6 @@ namespace scenes { }, button_size, button_alignment, button_margins ); -#ifdef _ONLINE_MULTIPLAYER_NOT_SUPPORTED - m_main_grid.get(online_button_id)->disable(); -#else - UNUSED(online_button_id); -#endif const auto ai_button_id = m_main_grid.add( service_provider, "vs AI", service_provider->font_manager().get(FontId::Default), Color::white(), diff --git a/src/scenes/online_lobby/online_lobby.cpp b/src/scenes/online_lobby/online_lobby.cpp index 9f2156a8..97f6670e 100644 --- a/src/scenes/online_lobby/online_lobby.cpp +++ b/src/scenes/online_lobby/online_lobby.cpp @@ -29,11 +29,12 @@ namespace scenes { } { //TODO(Totto): after the settings have been reworked, make this url changeable! - auto maybe_client = lobby::Client::get_client("http://127.0.0.1:5000"); - if (maybe_client.has_value()) { - m_client = std::make_unique(std::move(maybe_client.value())); + auto maybe_api = lobby::API::get_api("http://127.0.0.1:5000"); + if (maybe_api.has_value()) { + m_api = std::make_unique(std::move(maybe_api.value())); } else { - spdlog::error("Error in connecting to lobby client: {}", maybe_client.error()); + spdlog::error("Error in connecting to lobby API: {}", maybe_api.error()); + m_api = nullptr; } auto focus_helper = ui::FocusHelper{ 1 }; diff --git a/src/scenes/online_lobby/online_lobby.hpp b/src/scenes/online_lobby/online_lobby.hpp index 271907cb..6f31428b 100644 --- a/src/scenes/online_lobby/online_lobby.hpp +++ b/src/scenes/online_lobby/online_lobby.hpp @@ -17,7 +17,7 @@ namespace scenes { ui::TileLayout m_main_layout; std::optional m_next_command; - std::unique_ptr m_client{ nullptr }; + std::unique_ptr m_api; public: OOPETRIS_GRAPHICS_EXPORTED explicit OnlineLobby(ServiceProvider* service_provider, const ui::Layout& layout); diff --git a/src/scenes/scene.cpp b/src/scenes/scene.cpp index b1e27f9c..0e2cc551 100644 --- a/src/scenes/scene.cpp +++ b/src/scenes/scene.cpp @@ -1,16 +1,12 @@ -#if !defined(_ONLINE_MULTIPLAYER_NOT_SUPPORTED) -#include "online_lobby/online_lobby.hpp" -#endif - - +#include "scenes/scene.hpp" #include "about_page/about_page.hpp" #include "main_menu/main_menu.hpp" #include "multiplayer_menu/multiplayer_menu.hpp" +#include "online_lobby/online_lobby.hpp" #include "play_select_menu/play_select_menu.hpp" #include "recording_selector/recording_selector.hpp" #include "replay_game/replay_game.hpp" -#include "scenes/scene.hpp" #include "settings_menu/settings_menu.hpp" #include "single_player_game/single_player_game.hpp" @@ -37,10 +33,8 @@ namespace scenes { return std::make_unique(&service_provider, layout); case SceneId::RecordingSelectorMenu: return std::make_unique(&service_provider, layout); -#if !defined(_ONLINE_MULTIPLAYER_NOT_SUPPORTED) case SceneId::OnlineLobby: return std::make_unique(&service_provider, layout); -#endif //TODO(Totto): implement those /* case SceneId::LocalMultiPlayerGame: diff --git a/tools/dependencies/meson.build b/tools/dependencies/meson.build index 5ce100ed..204bf626 100644 --- a/tools/dependencies/meson.build +++ b/tools/dependencies/meson.build @@ -232,18 +232,23 @@ if build_application cpp_httlib_dep = dependency( 'cpp-httplib', required: false, + allow_fallback: true, default_options: { 'cpp-httplib_openssl': 'enabled', 'cpp-httplib_zlib': 'enabled', }, ) + online_multiplayer_user_fallback = false + if cpp_httlib_dep.found() graphics_lib += {'deps': [graphics_lib.get('deps'), cpp_httlib_dep]} else + online_multiplayer_user_fallback = true + curl_cpp_wrapper = dependency( 'cpr', required: true, From ebb834c659853b635a35bd67e90c1826309604c4 Mon Sep 17 00:00:00 2001 From: Totto16 Date: Wed, 23 Oct 2024 19:58:30 +0200 Subject: [PATCH 3/9] fix: httplib http backend: don't use namespace in cpp --- src/lobby/httplib_client.cpp | 116 ++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 57 deletions(-) diff --git a/src/lobby/httplib_client.cpp b/src/lobby/httplib_client.cpp index e1461f01..60893419 100644 --- a/src/lobby/httplib_client.cpp +++ b/src/lobby/httplib_client.cpp @@ -5,45 +5,44 @@ #define TRANSFORM_RESULT(result) std::make_unique((result)) -namespace oopetris::http::implementation { +oopetris::http::implementation::ActualResult::ActualResult(httplib::Result&& result) : m_result{ std::move(result) } { } +oopetris::http::implementation::ActualResult::~ActualResult() = default; - ActualResult::ActualResult(httplib::Result&& result) : m_result{ std::move(result) } { } - - ActualResult::~ActualResult() = default; - - [[nodiscard]] std::optional ActualResult::get_header(const std::string& key) const { - if (m_result->has_header(key)) { - return std::nullopt; - } - - return m_result->get_header_value(key); +[[nodiscard]] std::optional oopetris::http::implementation::ActualResult::get_header(const std::string& key +) const { + if (m_result->has_header(key)) { + return std::nullopt; } - [[nodiscard]] std::string ActualResult::body() const { - return m_result->body; - } + return m_result->get_header_value(key); +} - [[nodiscard]] int ActualResult::status() const { - return m_result->status; - } +[[nodiscard]] std::string oopetris::http::implementation::ActualResult::body() const { + return m_result->body; +} - [[nodiscard]] std::optional ActualResult::get_error() const { +[[nodiscard]] int oopetris::http::implementation::ActualResult::status() const { + return m_result->status; +} - if (not m_result) { - return httplib::to_string(m_result.error()); - } +[[nodiscard]] std::optional oopetris::http::implementation::ActualResult::get_error() const { - return std::nullopt; + if (not m_result) { + return httplib::to_string(m_result.error()); } + return std::nullopt; +} + - ActualClient::ActualClient(ActualClient&& other) noexcept : m_client{ std::move(other.m_client) } { } +oopetris::http::implementation::ActualClient::ActualClient(ActualClient&& other) noexcept + : m_client{ std::move(other.m_client) } { } - ActualClient::~ActualClient() = default; +oopetris::http::implementation::ActualClient::~ActualClient() = default; - ActualClient::ActualClient(const std::string& api_url) : m_client{ api_url } { - // clang-format off +oopetris::http::implementation::ActualClient::ActualClient(const std::string& api_url) : m_client{ api_url } { + // clang-format off m_client.set_default_headers({ #if defined(CPPHTTPLIB_ZLIB_SUPPORT) || defined(CPPHTTPLIB_BROTLI_SUPPORT) { "Accept-Encoding", @@ -59,49 +58,52 @@ namespace oopetris::http::implementation { #endif }, #endif - // clang-format on - { "Accept", ::http::constants::json_content_type } }); + // clang-format on + { "Accept", ::http::constants::json_content_type } }); #if defined(CPPHTTPLIB_ZLIB_SUPPORT) || defined(CPPHTTPLIB_BROTLI_SUPPORT) - m_client.set_compress(true); - m_client.set_decompress(true); + m_client.set_compress(true); + m_client.set_decompress(true); #endif - } - - [[nodiscard]] std::unique_ptr ActualClient::Get(const std::string& url) { - return TRANSFORM_RESULT(m_client.Get(url)); - } - - [[nodiscard]] std::unique_ptr ActualClient::Delete(const std::string& url) { - return TRANSFORM_RESULT(m_client.Delete(url)); - } +} - [[nodiscard]] std::unique_ptr - ActualClient::Post(const std::string& url, const std::optional>& payload) { +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Get(const std::string& url) { + return TRANSFORM_RESULT(m_client.Get(url)); +} - if (not payload.has_value()) { - return TRANSFORM_RESULT(m_client.Post(url)); - } +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Delete(const std::string& url) { + return TRANSFORM_RESULT(m_client.Delete(url)); +} - auto [content, content_type] = payload.value(); +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Post( + const std::string& url, + const std::optional>& payload +) { - return TRANSFORM_RESULT(m_client.Post(url, content, content_type)); + if (not payload.has_value()) { + return TRANSFORM_RESULT(m_client.Post(url)); } - [[nodiscard]] std::unique_ptr - ActualClient::Put(const std::string& url, const std::optional>& payload) { + auto [content, content_type] = payload.value(); - if (not payload.has_value()) { - return TRANSFORM_RESULT(m_client.Put(url)); - } + return TRANSFORM_RESULT(m_client.Post(url, content, content_type)); +} - auto [content, content_type] = payload.value(); +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Put( + const std::string& url, + const std::optional>& payload +) { - return TRANSFORM_RESULT(m_client.Put(url, content, content_type)); + if (not payload.has_value()) { + return TRANSFORM_RESULT(m_client.Put(url)); } - void ActualClient::SetBearerAuth(const std::string& token) { + auto [content, content_type] = payload.value(); - m_client.set_bearer_token_auth(token); - } -} // namespace oopetris::http::implementation + return TRANSFORM_RESULT(m_client.Put(url, content, content_type)); +} + +void oopetris::http::implementation::ActualClient::SetBearerAuth(const std::string& token) { + + m_client.set_bearer_token_auth(token); +} From 22215705edfb89bd11e7474ae1c764f4d23376ed Mon Sep 17 00:00:00 2001 From: Totto16 Date: Wed, 23 Oct 2024 21:51:52 +0200 Subject: [PATCH 4/9] feat: add curl / cpr (c++ curl wrapper) http backend --- src/lobby/client.cpp | 8 ++- src/lobby/curl_client.cpp | 130 +++++++++++++++++++++++++++++++++++ src/lobby/curl_client.hpp | 66 ++++++++++++++++++ src/lobby/httplib_client.hpp | 2 - 4 files changed, 203 insertions(+), 3 deletions(-) diff --git a/src/lobby/client.cpp b/src/lobby/client.cpp index 9a9b9841..c68fd11c 100644 --- a/src/lobby/client.cpp +++ b/src/lobby/client.cpp @@ -5,7 +5,13 @@ #if defined(_OOPETRIS_ONLINE_USE_CURL) #include "./curl_client.hpp" -#error "TODO" + + +std::string oopetris::http::status_message([[maybe_unused]] int status) { + return "Not Available"; +} + + #else #include "./httplib_client.hpp" diff --git a/src/lobby/curl_client.cpp b/src/lobby/curl_client.cpp index fe54bed5..81a8411e 100644 --- a/src/lobby/curl_client.cpp +++ b/src/lobby/curl_client.cpp @@ -1,2 +1,132 @@ #include "./curl_client.hpp" + + +#define TRANSFORM_RESULT(result) std::make_unique((result)) + + +oopetris::http::implementation::ActualResult::ActualResult(cpr::Response&& result) : m_result{ std::move(result) } { } + +oopetris::http::implementation::ActualResult::~ActualResult() = default; + +[[nodiscard]] std::optional oopetris::http::implementation::ActualResult::get_header(const std::string& key +) const { + + if (not m_result.header.contains(key)) { + return std::nullopt; + } + + return m_result.header.at(key); +} + +[[nodiscard]] std::string oopetris::http::implementation::ActualResult::body() const { + return m_result.text; +} + +[[nodiscard]] int oopetris::http::implementation::ActualResult::status() const { + return m_result.status_code; +} + +[[nodiscard]] std::optional oopetris::http::implementation::ActualResult::get_error() const { + + if (static_cast(m_result.error) || m_result.status_code == 0) { + return m_result.error.message; + } + + return std::nullopt; +} + + +namespace { + std::string normalize_url(const std::string& value) { + if (value.ends_with("/")) { + value.substr(0, value.size() - 1); + } + + return value; + } +} // namespace + +oopetris::http::implementation::ActualClient::ActualClient(ActualClient&& other) noexcept + : m_session{ std::move(other.m_session) } { } + +oopetris::http::implementation::ActualClient::~ActualClient() = default; + +oopetris::http::implementation::ActualClient::ActualClient(const std::string& api_url) + : m_session{}, + m_base_url{ normalize_url(api_url) } { + + m_session.SetUrl(cpr::Url{ api_url }); + m_session.SetAcceptEncoding(cpr::AcceptEncoding{ + { cpr::AcceptEncodingMethods::deflate, cpr::AcceptEncodingMethods::gzip, + cpr::AcceptEncodingMethods::zlib } + }); + m_session.SetHeader(cpr::Header{ + { "Accept", ::http::constants::json_content_type } + }); +} + + +void oopetris::http::implementation::ActualClient::set_url(const std::string& url) { + m_session.SetUrl(cpr::Url{ m_base_url, url }); +} + + +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Get( + const std::string& url +) { + set_url(url); + return TRANSFORM_RESULT(m_session.Get()); +} + +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Delete( + const std::string& url +) { + set_url(url); + return TRANSFORM_RESULT(m_session.Delete()); +} + +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Post( + const std::string& url, + const std::optional>& payload +) { + + set_url(url); + + if (not payload.has_value()) { + return TRANSFORM_RESULT(m_session.Post()); + } + + auto [content, content_type] = payload.value(); + + m_session.SetBody(cpr::Body{ content }); + + return TRANSFORM_RESULT(m_session.Post()); +} + +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Put( + const std::string& url, + const std::optional>& payload +) { + set_url(url); + + if (not payload.has_value()) { + return TRANSFORM_RESULT(m_session.Put()); + } + + auto [content, content_type] = payload.value(); + + m_session.SetBody(cpr::Body{ content }); + + return TRANSFORM_RESULT(m_session.Put()); +} + +void oopetris::http::implementation::ActualClient::SetBearerAuth(const std::string& token) { + + +#if CPR_LIBCURL_VERSION_NUM >= 0x073D00 + m_session.SetBearer(token); +#else + m_session.SetHeader(cpr::Header{ "Authorization", fmt::format("Bearer {}", token) }); +#endif +} diff --git a/src/lobby/curl_client.hpp b/src/lobby/curl_client.hpp index 99ddf32d..97c3ab23 100644 --- a/src/lobby/curl_client.hpp +++ b/src/lobby/curl_client.hpp @@ -1,2 +1,68 @@ #pragma once + + +#include "./client.hpp" + +#include + +namespace oopetris::http::implementation { + + struct ActualResult : ::oopetris::http::Result { + private: + cpr::Response m_result; + + + public: + OOPETRIS_GRAPHICS_EXPORTED ActualResult(cpr::Response&& result); + + OOPETRIS_GRAPHICS_EXPORTED ~ActualResult() override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::optional get_header(const std::string& key + ) const override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::string body() const override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] int status() const override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::optional get_error() const override; + }; + + + struct ActualClient : ::oopetris::http::Client { + private: + cpr::Session m_session; + std::string m_base_url; + + void set_url(const std::string& url); + + public: + OOPETRIS_GRAPHICS_EXPORTED ActualClient(ActualClient&& other) noexcept; + OOPETRIS_GRAPHICS_EXPORTED ActualClient& operator=(ActualClient&& other) noexcept = delete; + + OOPETRIS_GRAPHICS_EXPORTED ActualClient(const ActualClient& other) = delete; + OOPETRIS_GRAPHICS_EXPORTED ActualClient& operator=(const ActualClient& other) = delete; + + OOPETRIS_GRAPHICS_EXPORTED ~ActualClient() override; + + OOPETRIS_GRAPHICS_EXPORTED explicit ActualClient(const std::string& api_url); + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Get(const std::string& url) override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Delete(const std::string& url) override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Post( + const std::string& url, + const std::optional>& payload = std::nullopt + ) override; + + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Put( + const std::string& url, + const std::optional>& payload = std::nullopt + ) override; + + OOPETRIS_GRAPHICS_EXPORTED void SetBearerAuth(const std::string& token) override; + }; + + +} // namespace oopetris::http::implementation diff --git a/src/lobby/httplib_client.hpp b/src/lobby/httplib_client.hpp index 9202e31d..f87c20a6 100644 --- a/src/lobby/httplib_client.hpp +++ b/src/lobby/httplib_client.hpp @@ -20,10 +20,8 @@ #pragma warning(default : 4100) #endif - #include "./client.hpp" - namespace oopetris::http::implementation { struct ActualResult : ::oopetris::http::Result { From 1c84c21917c5bc447de664de441f8bed240f2ce9 Mon Sep 17 00:00:00 2001 From: Totto16 Date: Wed, 23 Oct 2024 22:42:08 +0200 Subject: [PATCH 5/9] fix: fix a few minor issues regarding the curl http backend also fix clang-tidy warnings --- .clang-tidy | 2 +- src/lobby/api.cpp | 6 +++--- src/lobby/client.hpp | 31 ++++++++++++++++++++----------- src/lobby/curl_client.cpp | 13 ++++++++----- src/lobby/curl_client.hpp | 20 +++++++++++--------- src/lobby/httplib_client.cpp | 14 +++++++++++--- src/lobby/httplib_client.hpp | 20 +++++++++++--------- 7 files changed, 65 insertions(+), 41 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index f7a36a5d..4612c0ef 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,6 @@ # taken from https://github.com/cpp-linter/cpp-linter-action/blob/main/demo/.clang-tidy --- -Checks: "clang-diagnostic-*,clang-analyzer-*,bugprone-*,misc-*,performance-*,readability-*,portability-*,modernize-*,cppcoreguidelines-*,google-*,llvm-*,cert-*,-modernize-use-trailing-return-type,-bugprone-argument-comment,-misc-include-cleaner,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-readability-avoid-nested-conditional-operator,-llvm-namespace-comment,-llvm-header-guard" +Checks: "clang-diagnostic-*,clang-analyzer-*,bugprone-*,misc-*,performance-*,readability-*,portability-*,modernize-*,cppcoreguidelines-*,google-*,llvm-*,cert-*,-modernize-use-trailing-return-type,-bugprone-argument-comment,-misc-include-cleaner,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers,-readability-avoid-nested-conditional-operator,-llvm-namespace-comment,-llvm-header-guard,-google-build-explicit-make-pair" WarningsAsErrors: "" HeaderFilterRegex: "oopetris/src/.*" FormatStyle: "file" diff --git a/src/lobby/api.cpp b/src/lobby/api.cpp index f41880df..29248eb3 100644 --- a/src/lobby/api.cpp +++ b/src/lobby/api.cpp @@ -129,7 +129,7 @@ helper::expected lobby::API::join_lobby(int lobby_id) { }; } - auto res = m_client->Post(fmt::format("/lobbies/{}", lobby_id)); + auto res = m_client->Post(fmt::format("/lobbies/{}", lobby_id), std::nullopt); return is_request_ok(res, 204); } @@ -168,7 +168,7 @@ helper::expected lobby::API::leave_lobby(int lobby_id) { }; } - auto res = m_client->Put(fmt::format("/lobbies/{}/leave", lobby_id)); + auto res = m_client->Put(fmt::format("/lobbies/{}/leave", lobby_id), std::nullopt); return is_request_ok(res, 204); } @@ -181,7 +181,7 @@ helper::expected lobby::API::start_lobby(int lobby_id) { }; } - auto res = m_client->Post(fmt::format("/lobbies/{}/start", lobby_id)); + auto res = m_client->Post(fmt::format("/lobbies/{}/start", lobby_id), std::nullopt); return is_request_ok(res, 204); } diff --git a/src/lobby/client.hpp b/src/lobby/client.hpp index a255a25b..e05f0bab 100644 --- a/src/lobby/client.hpp +++ b/src/lobby/client.hpp @@ -17,7 +17,8 @@ namespace oopetris::http { - struct Result { + + struct Result { //NOLINT(cppcoreguidelines-special-member-functions) OOPETRIS_GRAPHICS_EXPORTED virtual ~Result(); OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::optional get_header(const std::string& key @@ -30,34 +31,42 @@ namespace oopetris::http { OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::optional get_error() const = 0; }; - struct Client { + struct Client { //NOLINT(cppcoreguidelines-special-member-functions) OOPETRIS_GRAPHICS_EXPORTED virtual ~Client(); - OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr Get(const std::string& url) = 0; + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr + Get( //NOLINT(readability-identifier-naming) + const std::string& url + ) = 0; - OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr Delete(const std::string& url) = 0; + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr + Delete( //NOLINT(readability-identifier-naming) + const std::string& url + ) = 0; - OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr Post( + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr + Post( //NOLINT(readability-identifier-naming) const std::string& url, - const std::optional>& payload = std::nullopt + const std::optional>& payload ) = 0; - OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr Put( + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] virtual std::unique_ptr + Put( //NOLINT(readability-identifier-naming) const std::string& url, - const std::optional>& payload = std::nullopt + const std::optional>& payload ) = 0; - OOPETRIS_GRAPHICS_EXPORTED virtual void SetBearerAuth(const std::string& token) = 0; + OOPETRIS_GRAPHICS_EXPORTED virtual void SetBearerAuth( //NOLINT(readability-identifier-naming) + const std::string& token + ) = 0; }; - OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::string status_message(int status); OOPETRIS_GRAPHICS_EXPORTED helper::expected is_json_response( const std::unique_ptr& result ); - OOPETRIS_GRAPHICS_EXPORTED helper::expected is_error_message_response( const std::unique_ptr& result ); diff --git a/src/lobby/curl_client.cpp b/src/lobby/curl_client.cpp index 81a8411e..b6eee2a6 100644 --- a/src/lobby/curl_client.cpp +++ b/src/lobby/curl_client.cpp @@ -2,13 +2,16 @@ #include "./curl_client.hpp" -#define TRANSFORM_RESULT(result) std::make_unique((result)) +#define TRANSFORM_RESULT(result) std::make_unique((result)) //NOLINT(cppcoreguidelines-macro-usage) oopetris::http::implementation::ActualResult::ActualResult(cpr::Response&& result) : m_result{ std::move(result) } { } oopetris::http::implementation::ActualResult::~ActualResult() = default; +oopetris::http::implementation::ActualResult::ActualResult(ActualResult&& other) noexcept + : m_result{ std::move(other.m_result) } { } + [[nodiscard]] std::optional oopetris::http::implementation::ActualResult::get_header(const std::string& key ) const { @@ -24,7 +27,7 @@ oopetris::http::implementation::ActualResult::~ActualResult() = default; } [[nodiscard]] int oopetris::http::implementation::ActualResult::status() const { - return m_result.status_code; + return static_cast(m_result.status_code); } [[nodiscard]] std::optional oopetris::http::implementation::ActualResult::get_error() const { @@ -40,7 +43,7 @@ oopetris::http::implementation::ActualResult::~ActualResult() = default; namespace { std::string normalize_url(const std::string& value) { if (value.ends_with("/")) { - value.substr(0, value.size() - 1); + return value.substr(0, value.size() - 1); } return value; @@ -52,9 +55,9 @@ oopetris::http::implementation::ActualClient::ActualClient(ActualClient&& other) oopetris::http::implementation::ActualClient::~ActualClient() = default; + oopetris::http::implementation::ActualClient::ActualClient(const std::string& api_url) - : m_session{}, - m_base_url{ normalize_url(api_url) } { + : m_base_url{ normalize_url(api_url) } { m_session.SetUrl(cpr::Url{ api_url }); m_session.SetAcceptEncoding(cpr::AcceptEncoding{ diff --git a/src/lobby/curl_client.hpp b/src/lobby/curl_client.hpp index 97c3ab23..cadbc747 100644 --- a/src/lobby/curl_client.hpp +++ b/src/lobby/curl_client.hpp @@ -14,10 +14,16 @@ namespace oopetris::http::implementation { public: - OOPETRIS_GRAPHICS_EXPORTED ActualResult(cpr::Response&& result); + OOPETRIS_GRAPHICS_EXPORTED explicit ActualResult(cpr::Response&& result); OOPETRIS_GRAPHICS_EXPORTED ~ActualResult() override; + OOPETRIS_GRAPHICS_EXPORTED ActualResult(ActualResult&& other) noexcept; + OOPETRIS_GRAPHICS_EXPORTED ActualResult& operator=(ActualResult&& other) noexcept = delete; + + OOPETRIS_GRAPHICS_EXPORTED ActualResult(const ActualResult& other) = delete; + OOPETRIS_GRAPHICS_EXPORTED ActualResult& operator=(const ActualResult& other) = delete; + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::optional get_header(const std::string& key ) const override; @@ -51,15 +57,11 @@ namespace oopetris::http::implementation { OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Delete(const std::string& url) override; - OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Post( - const std::string& url, - const std::optional>& payload = std::nullopt - ) override; + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr + Post(const std::string& url, const std::optional>& payload) override; - OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Put( - const std::string& url, - const std::optional>& payload = std::nullopt - ) override; + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr + Put(const std::string& url, const std::optional>& payload) override; OOPETRIS_GRAPHICS_EXPORTED void SetBearerAuth(const std::string& token) override; }; diff --git a/src/lobby/httplib_client.cpp b/src/lobby/httplib_client.cpp index 60893419..a394d3b0 100644 --- a/src/lobby/httplib_client.cpp +++ b/src/lobby/httplib_client.cpp @@ -2,13 +2,17 @@ #include "./httplib_client.hpp" -#define TRANSFORM_RESULT(result) std::make_unique((result)) +#define TRANSFORM_RESULT(result) std::make_unique((result)) //NOLINT(cppcoreguidelines-macro-usage oopetris::http::implementation::ActualResult::ActualResult(httplib::Result&& result) : m_result{ std::move(result) } { } oopetris::http::implementation::ActualResult::~ActualResult() = default; + +oopetris::http::implementation::ActualResult::ActualResult(ActualResult&& other) noexcept + : m_result{ std::move(other.m_result) } { } + [[nodiscard]] std::optional oopetris::http::implementation::ActualResult::get_header(const std::string& key ) const { if (m_result->has_header(key)) { @@ -67,11 +71,15 @@ oopetris::http::implementation::ActualClient::ActualClient(const std::string& ap #endif } -[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Get(const std::string& url) { +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Get( + const std::string& url +) { return TRANSFORM_RESULT(m_client.Get(url)); } -[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Delete(const std::string& url) { +[[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Delete( + const std::string& url +) { return TRANSFORM_RESULT(m_client.Delete(url)); } diff --git a/src/lobby/httplib_client.hpp b/src/lobby/httplib_client.hpp index f87c20a6..c8d1858a 100644 --- a/src/lobby/httplib_client.hpp +++ b/src/lobby/httplib_client.hpp @@ -29,10 +29,16 @@ namespace oopetris::http::implementation { httplib::Result m_result; public: - OOPETRIS_GRAPHICS_EXPORTED ActualResult(httplib::Result&& result); + OOPETRIS_GRAPHICS_EXPORTED explicit ActualResult(httplib::Result&& result); OOPETRIS_GRAPHICS_EXPORTED ~ActualResult() override; + OOPETRIS_GRAPHICS_EXPORTED ActualResult(ActualResult&& other) noexcept; + OOPETRIS_GRAPHICS_EXPORTED ActualResult& operator=(ActualResult&& other) noexcept = delete; + + OOPETRIS_GRAPHICS_EXPORTED ActualResult(const ActualResult& other) = delete; + OOPETRIS_GRAPHICS_EXPORTED ActualResult& operator=(const ActualResult& other) = delete; + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::optional get_header(const std::string& key ) const override; @@ -63,15 +69,11 @@ namespace oopetris::http::implementation { OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Delete(const std::string& url) override; - OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Post( - const std::string& url, - const std::optional>& payload = std::nullopt - ) override; + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr + Post(const std::string& url, const std::optional>& payload) override; - OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr Put( - const std::string& url, - const std::optional>& payload = std::nullopt - ) override; + OOPETRIS_GRAPHICS_EXPORTED [[nodiscard]] std::unique_ptr + Put(const std::string& url, const std::optional>& payload) override; OOPETRIS_GRAPHICS_EXPORTED void SetBearerAuth(const std::string& token) override; }; From 8a1c7fb11f67391beca2d730c429830ebc87856f Mon Sep 17 00:00:00 2001 From: Totto16 Date: Wed, 23 Oct 2024 22:59:26 +0200 Subject: [PATCH 6/9] ci: ignore files, that can't be checked, since the header is missing --- .github/workflows/cpp-linter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cpp-linter.yml b/.github/workflows/cpp-linter.yml index afb94790..4e440b3f 100644 --- a/.github/workflows/cpp-linter.yml +++ b/.github/workflows/cpp-linter.yml @@ -51,7 +51,7 @@ jobs: tidy-checks: '' step-summary: true file-annotations: true - ignore: subprojects|build|android|assets|recordings|docs|toolchains|platforms|wrapper|src/libs/core/hash-library + ignore: subprojects|build|android|assets|recordings|docs|toolchains|platforms|wrapper|src/libs/core/hash-library|src/lobby/curl_client.* - name: Fail CI run if linter checks failed if: steps.linter.outputs.checks-failed != 0 From f89fb41fa7b55c6f7dccab48a2eced42a4fa76c4 Mon Sep 17 00:00:00 2001 From: Totto16 Date: Wed, 23 Oct 2024 23:02:07 +0200 Subject: [PATCH 7/9] dependencies: update cpr (curl c++ wrapper) tto 1.11.0 --- subprojects/cpr.wrap | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/subprojects/cpr.wrap b/subprojects/cpr.wrap index 601df204..3ff2dbdb 100644 --- a/subprojects/cpr.wrap +++ b/subprojects/cpr.wrap @@ -1,13 +1,13 @@ [wrap-file] -directory = cpr-1.10.5 -source_url = https://github.com/libcpr/cpr/archive/1.10.5.tar.gz -source_filename = cpr-1.10.5.tar.gz -source_hash = c8590568996cea918d7cf7ec6845d954b9b95ab2c4980b365f582a665dea08d8 -patch_filename = cpr_1.10.5-1_patch.zip -patch_url = https://wrapdb.mesonbuild.com/v2/cpr_1.10.5-1/get_patch -patch_hash = 01e31e1bd47bc55dabc8e3b0633451abefc37532ba57b3ba3f0a304592ea5ac5 -source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/cpr_1.10.5-1/cpr-1.10.5.tar.gz -wrapdb_version = 1.10.5-1 +directory = cpr-1.11.0 +source_url = https://github.com/libcpr/cpr/archive/1.11.0.tar.gz +source_filename = cpr-1.11.0.tar.gz +source_hash = fdafa3e3a87448b5ddbd9c7a16e7276a78f28bbe84a3fc6edcfef85eca977784 +patch_filename = cpr_1.11.0-1_patch.zip +patch_url = https://wrapdb.mesonbuild.com/v2/cpr_1.11.0-1/get_patch +patch_hash = 63b94f2524d1d2ab433583c3490d80f1027d68fb7a709e44ee43dbb51f4b3040 +source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/cpr_1.11.0-1/cpr-1.11.0.tar.gz +wrapdb_version = 1.11.0-1 [provide] cpr = cpr_dep From 2d068f9f7a965bca701aadc2e6e15b1df7ba5f93 Mon Sep 17 00:00:00 2001 From: Totto16 Date: Wed, 23 Oct 2024 23:23:53 +0200 Subject: [PATCH 8/9] fix: fix curl http backend, after update of cpr --- src/lobby/curl_client.cpp | 28 ++++++++++++++-------------- src/lobby/curl_client.hpp | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/lobby/curl_client.cpp b/src/lobby/curl_client.cpp index b6eee2a6..bc5e7a32 100644 --- a/src/lobby/curl_client.cpp +++ b/src/lobby/curl_client.cpp @@ -59,19 +59,19 @@ oopetris::http::implementation::ActualClient::~ActualClient() = default; oopetris::http::implementation::ActualClient::ActualClient(const std::string& api_url) : m_base_url{ normalize_url(api_url) } { - m_session.SetUrl(cpr::Url{ api_url }); - m_session.SetAcceptEncoding(cpr::AcceptEncoding{ + m_session->SetUrl(cpr::Url{ api_url }); + m_session->SetAcceptEncoding(cpr::AcceptEncoding{ { cpr::AcceptEncodingMethods::deflate, cpr::AcceptEncodingMethods::gzip, cpr::AcceptEncodingMethods::zlib } }); - m_session.SetHeader(cpr::Header{ + m_session->SetHeader(cpr::Header{ { "Accept", ::http::constants::json_content_type } }); } void oopetris::http::implementation::ActualClient::set_url(const std::string& url) { - m_session.SetUrl(cpr::Url{ m_base_url, url }); + m_session->SetUrl(cpr::Url{ m_base_url, url }); } @@ -79,14 +79,14 @@ void oopetris::http::implementation::ActualClient::set_url(const std::string& ur const std::string& url ) { set_url(url); - return TRANSFORM_RESULT(m_session.Get()); + return TRANSFORM_RESULT(m_session->Get()); } [[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Delete( const std::string& url ) { set_url(url); - return TRANSFORM_RESULT(m_session.Delete()); + return TRANSFORM_RESULT(m_session->Delete()); } [[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Post( @@ -97,14 +97,14 @@ void oopetris::http::implementation::ActualClient::set_url(const std::string& ur set_url(url); if (not payload.has_value()) { - return TRANSFORM_RESULT(m_session.Post()); + return TRANSFORM_RESULT(m_session->Post()); } auto [content, content_type] = payload.value(); - m_session.SetBody(cpr::Body{ content }); + m_session->SetBody(cpr::Body{ content }); - return TRANSFORM_RESULT(m_session.Post()); + return TRANSFORM_RESULT(m_session->Post()); } [[nodiscard]] std::unique_ptr oopetris::http::implementation::ActualClient::Put( @@ -114,22 +114,22 @@ void oopetris::http::implementation::ActualClient::set_url(const std::string& ur set_url(url); if (not payload.has_value()) { - return TRANSFORM_RESULT(m_session.Put()); + return TRANSFORM_RESULT(m_session->Put()); } auto [content, content_type] = payload.value(); - m_session.SetBody(cpr::Body{ content }); + m_session->SetBody(cpr::Body{ content }); - return TRANSFORM_RESULT(m_session.Put()); + return TRANSFORM_RESULT(m_session->Put()); } void oopetris::http::implementation::ActualClient::SetBearerAuth(const std::string& token) { #if CPR_LIBCURL_VERSION_NUM >= 0x073D00 - m_session.SetBearer(token); + m_session->SetBearer(token); #else - m_session.SetHeader(cpr::Header{ "Authorization", fmt::format("Bearer {}", token) }); + m_session->SetHeader(cpr::Header{ "Authorization", fmt::format("Bearer {}", token) }); #endif } diff --git a/src/lobby/curl_client.hpp b/src/lobby/curl_client.hpp index cadbc747..7502b50b 100644 --- a/src/lobby/curl_client.hpp +++ b/src/lobby/curl_client.hpp @@ -37,7 +37,7 @@ namespace oopetris::http::implementation { struct ActualClient : ::oopetris::http::Client { private: - cpr::Session m_session; + std::unique_ptr m_session; std::string m_base_url; void set_url(const std::string& url); From fe35a2578eed0bf5a08e6bf81f8d3c0c62708b91 Mon Sep 17 00:00:00 2001 From: Totto16 Date: Wed, 23 Oct 2024 23:33:14 +0200 Subject: [PATCH 9/9] fix: suppress warning for 3ds in cpr --- src/lobby/curl_client.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/lobby/curl_client.hpp b/src/lobby/curl_client.hpp index 7502b50b..1c9abce5 100644 --- a/src/lobby/curl_client.hpp +++ b/src/lobby/curl_client.hpp @@ -4,8 +4,20 @@ #include "./client.hpp" +#if defined(__3DS__) + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + #include + +#if defined(__3DS__) +#pragma GCC diagnostic pop +#endif + + namespace oopetris::http::implementation { struct ActualResult : ::oopetris::http::Result {