From d78c6cecd8ce07a1ddcf9dea080f86f88eb6712b Mon Sep 17 00:00:00 2001 From: Snider Date: Thu, 9 Oct 2025 13:44:34 +0100 Subject: [PATCH 1/2] Add initial Oatpp-based API server implementation Introduces a new API module using Oatpp and Oatpp-Swagger, including controllers, DTOs, and server setup. Updates build scripts and dependencies to support the new API layer for Lethean, providing endpoints and Swagger documentation. --- conanfile.py | 4 +- src/CMakeLists.txt | 1 + src/api/ApiServer.hpp | 38 +++++++++++ src/api/CMakeLists.txt | 30 +++++++++ src/api/controller/RootController.hpp | 35 ++++++++++ src/api/controller/info/InfoController.hpp | 37 +++++++++++ src/api/dto/DTOs.hpp | 36 ++++++++++ src/api/main.cpp | 76 ++++++++++++++++++++++ 8 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 src/api/ApiServer.hpp create mode 100644 src/api/CMakeLists.txt create mode 100644 src/api/controller/RootController.hpp create mode 100644 src/api/controller/info/InfoController.hpp create mode 100644 src/api/dto/DTOs.hpp create mode 100644 src/api/main.cpp diff --git a/conanfile.py b/conanfile.py index ab1a89cb..69cd53e7 100644 --- a/conanfile.py +++ b/conanfile.py @@ -26,7 +26,9 @@ class BlockchainConan(ConanFile): "boost/1.85.0", "openssl/3.2.0", "miniupnpc/2.2.5", - "jwt-cpp/0.7.1" + "jwt-cpp/0.7.1", + "oatpp/1.3.0.latest", + "oatpp-swagger/1.3.0.latest" ] def generate(self): diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 541dc852..2132a36a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -85,6 +85,7 @@ INIT_SHARED_PCH() add_subdirectory(config) add_subdirectory(genesis) +add_subdirectory(api) add_library(common ${COMMON}) add_dependencies(common version config ${PCH_LIB_NAME}) diff --git a/src/api/ApiServer.hpp b/src/api/ApiServer.hpp new file mode 100644 index 00000000..2aa6f74a --- /dev/null +++ b/src/api/ApiServer.hpp @@ -0,0 +1,38 @@ +#ifndef ApiServer_hpp +#define ApiServer_hpp + +#include "oatpp/web/server/HttpConnectionHandler.hpp" +#include "oatpp/network/tcp/server/ConnectionProvider.hpp" +#include "oatpp/core/macro/component.hpp" +#include "oatpp-swagger/Resources.hpp" + +#include "oatpp/parser/json/mapping/ObjectMapper.hpp" +#include "oatpp-swagger/Resources.hpp" +#include "oatpp-swagger/Model.hpp" +class ApiServer { +public: + + OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionProvider)([] { + return oatpp::network::tcp::server::ConnectionProvider::createShared({"0.0.0.0", 8000, oatpp::network::Address::IP_4}); + }()); + + OATPP_CREATE_COMPONENT(std::shared_ptr, httpRouter)([] { + return oatpp::web::server::HttpRouter::createShared(); + }()); + + OATPP_CREATE_COMPONENT(std::shared_ptr, serverConnectionHandler)([] { + OATPP_COMPONENT(std::shared_ptr, router); + return oatpp::web::server::HttpConnectionHandler::createShared(router); + }()); + + OATPP_CREATE_COMPONENT(std::shared_ptr, apiObjectMapper)([] { + return oatpp::parser::json::mapping::ObjectMapper::createShared(); + }()); + + OATPP_CREATE_COMPONENT(std::shared_ptr, swaggerResources)([] { + return oatpp::swagger::Resources::loadResources(OATPP_SWAGGER_RES_PATH); + }()); + +}; + +#endif /* ApiServer_hpp */ diff --git a/src/api/CMakeLists.txt b/src/api/CMakeLists.txt new file mode 100644 index 00000000..cb452681 --- /dev/null +++ b/src/api/CMakeLists.txt @@ -0,0 +1,30 @@ +if(NOT PROJECT_NAME) + project(lethean-api) +endif() + +find_package(oatpp 1.3.0 REQUIRED) +if(oatpp_FOUND) + message(STATUS "Found oatpp version: ${oatpp_VERSION_STRING}") +else() + message(FATAL_ERROR "Could not find oatpp") +endif() + +find_package(oatpp-swagger 1.3.0 REQUIRED) +if(oatpp-swagger_FOUND) + message(STATUS "Found oatpp-swagger version: ${oatpp-swagger_VERSION_STRING}") +else() + message(FATAL_ERROR "Could not find oatpp-swagger") +endif() + +add_library(lthn_api INTERFACE) +add_library(lthn::api ALIAS lthn_api) + +target_include_directories(lthn_api INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${oatpp_INCLUDE_DIRS}) +include_directories(${oatpp-swagger_INCLUDE_DIRS}) +add_executable(lethean-api main.cpp) + +target_link_libraries(lethean-api PRIVATE lthn::api PUBLIC oatpp::oatpp oatpp::oatpp-swagger) + +add_definitions(-DOATPP_SWAGGER_RES_PATH="${oatpp-swagger_INCLUDE_DIRS}/../bin/oatpp-swagger/res") +#add_subdirectory(tests) diff --git a/src/api/controller/RootController.hpp b/src/api/controller/RootController.hpp new file mode 100644 index 00000000..37dd5745 --- /dev/null +++ b/src/api/controller/RootController.hpp @@ -0,0 +1,35 @@ +#ifndef RootController_hpp +#define RootController_hpp + +#include "./info/InfoController.hpp" +#include "../dto/DTOs.hpp" + +#include "oatpp/web/server/api/ApiController.hpp" +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/macro/component.hpp" + +#include OATPP_CODEGEN_BEGIN(ApiController) + +class RootController : public oatpp::web::server::api::ApiController { +private: + std::shared_ptr m_infoController; +public: + RootController(OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper), + m_infoController(std::make_shared(objectMapper)) + {} +public: + + // oatpp::web::server::api::Endpoints(m_infoController, "/info"); + + ENDPOINT("GET", "/hello", root) { + auto dto = MyDto::createShared(); + dto->message = "Hello World!"; + return createDtoResponse(Status::CODE_200, dto); + } + +}; + +#include OATPP_CODEGEN_END(ApiController) + +#endif /* RootController_hpp */ diff --git a/src/api/controller/info/InfoController.hpp b/src/api/controller/info/InfoController.hpp new file mode 100644 index 00000000..ab2ece69 --- /dev/null +++ b/src/api/controller/info/InfoController.hpp @@ -0,0 +1,37 @@ +#ifndef InfoController_hpp +#define InfoController_hpp + +#include "oatpp/web/server/api/ApiController.hpp" +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/macro/component.hpp" + +#include OATPP_CODEGEN_BEGIN(ApiController) + +class InfoController : public oatpp::web::server::api::ApiController { +public: + InfoController(OATPP_COMPONENT(std::shared_ptr, objectMapper)) + : oatpp::web::server::api::ApiController(objectMapper) + {} +public: + + ENDPOINT_INFO(version) { + info->summary = "Get API version"; + info->description = "Returns the current version of the API."; + } + ENDPOINT("GET", "/version", version) { + return createResponse(Status::CODE_200, "v0.0.1"); + } + + ENDPOINT_INFO(root) { + info->summary = "Get info root"; + info->description = "Returns a placeholder for the info root."; + } + ENDPOINT("GET", "/", root) { + return createResponse(Status::CODE_200, "Info root"); + } + +}; + +#include OATPP_CODEGEN_END(ApiController) + +#endif /* InfoController_hpp */ diff --git a/src/api/dto/DTOs.hpp b/src/api/dto/DTOs.hpp new file mode 100644 index 00000000..e8bd3111 --- /dev/null +++ b/src/api/dto/DTOs.hpp @@ -0,0 +1,36 @@ +// Copyright (c) 2014-2018 Zano Project +// Copyright (c) 2014-2018 The Louisdor Project +// Copyright (c) 2012-2013 The Boolberry developers +// Copyright (c) 2017-2025 Lethean (https://lt.hn) +// +// Licensed under the European Union Public Licence (EUPL) version 1.2. +// You may obtain a copy of the licence at: +// +// https://joinup.ec.europa.eu/software/page/eupl/licence-eupl +// +// The EUPL is a copyleft licence that is compatible with the MIT/X11 +// licence used by the original projects; the MIT terms are therefore +// considered “grandfathered” under the EUPL for this code. +// +// SPDX‑License‑Identifier: EUPL-1.2 +// + +#ifndef DTOs_hpp +#define DTOs_hpp + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" + +#include OATPP_CODEGEN_BEGIN(DTO) + +class MyDto : public oatpp::DTO { + + DTO_INIT(MyDto, DTO); + + DTO_FIELD(String, message); + +}; + +#include OATPP_CODEGEN_END(DTO) + +#endif /* DTOs_hpp */ diff --git a/src/api/main.cpp b/src/api/main.cpp new file mode 100644 index 00000000..dbea164d --- /dev/null +++ b/src/api/main.cpp @@ -0,0 +1,76 @@ +#include "controller/RootController.hpp" +#include "ApiServer.hpp" + +#include "oatpp/network/Server.hpp" +#include "oatpp-swagger/Controller.hpp" + +#include + +void run() { + /* Register Components in scope of run() method */ + ApiServer components; + + /* Get router component */ + OATPP_COMPONENT(std::shared_ptr, router); + + /* Create RootController and add all of its endpoints to router */ + auto rootController = std::make_shared(); + router->addController(rootController); + + OATPP_CREATE_COMPONENT(std::shared_ptr, swaggerDocumentInfo)([] { + + oatpp::swagger::DocumentInfo::Builder builder; + + builder + .setTitle("Lethean Blockchain API") + .setDescription("New API layer for Lethean") + .setVersion("1.0") + .setContactName("Lethean") + .setContactUrl("https://lt.hn/") + + .setLicenseName("EUPL-1.2") + .setLicenseUrl("https://joinup.ec.europa.eu/software/page/eupl/licence-eupl") + + .addServer("http://localhost:8000", "server on localhost"); + + // When you are using the AUTHENTICATION() Endpoint-Macro you must add an SecurityScheme object (https://swagger.io/specification/#securitySchemeObject) + // For basic-authentication you can use the default Basic-Authorization-Security-Scheme like this + // For more complex authentication schemes you can use the oatpp::swagger::DocumentInfo::SecuritySchemeBuilder builder + // Don't forget to add info->addSecurityRequirement("basic_auth") to your ENDPOINT_INFO() Macro! + //.addSecurityScheme("basic_auth", oatpp::swagger::DocumentInfo::SecuritySchemeBuilder::DefaultBasicAuthorizationSecurityScheme()); + + return builder.build(); + +}()); + + /* Create Swagger-UI controller and add its endpoints to router */ + auto swaggerController = oatpp::swagger::Controller::createShared(rootController->getEndpoints()); + router->addController(swaggerController); + + /* Get connection handler component */ + OATPP_COMPONENT(std::shared_ptr, connectionHandler); + + /* Get connection provider component */ + OATPP_COMPONENT(std::shared_ptr, connectionProvider); + + /* Create server which takes provided TCP connections and passes them to HTTP connection handler */ + oatpp::network::Server server(connectionProvider, connectionHandler); + + /* Print server port */ + OATPP_LOGI("lethean-api", "Server running on port %s", connectionProvider->getProperty("port").getData()); + + /* Run server */ + server.run(); +} + +int main(int argc, const char * argv[]) { + + oatpp::base::Environment::init(); + + run(); + + /* Destroy oatpp Environment */ + oatpp::base::Environment::destroy(); + + return 0; +} From c5c90dad6b3cb923670f97547b72fcd5b9664992 Mon Sep 17 00:00:00 2001 From: Snider Date: Thu, 9 Oct 2025 15:38:58 +0100 Subject: [PATCH 2/2] Update docs --- docs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs b/docs index 12e20efc..5f842e05 160000 --- a/docs +++ b/docs @@ -1 +1 @@ -Subproject commit 12e20efce7eaf51e38d8953c318633b1c5189256 +Subproject commit 5f842e053886802d3ef5322e19442c84f3b4aa63