mirror of
https://gitee.com/an-tao/drogon.git
synced 2024-11-29 18:27:43 +08:00
Add support to yaml config file. (#1521)
Co-authored-by: an-tao <antao2002@gmail.com>
This commit is contained in:
parent
57ec87d38d
commit
d4c0e063f1
@ -210,6 +210,16 @@ find_package(Jsoncpp REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC Jsoncpp_lib)
|
||||
list(APPEND INCLUDE_DIRS_FOR_DYNAMIC_VIEW ${JSONCPP_INCLUDE_DIRS})
|
||||
|
||||
# yamlcpp
|
||||
find_package(yaml-cpp QUIET)
|
||||
if(yaml-cpp_FOUND)
|
||||
message(STATUS "yaml-cpp found")
|
||||
target_link_libraries(${PROJECT_NAME} PUBLIC ${YAML_CPP_LIBRARIES})
|
||||
target_compile_definitions(${PROJECT_NAME} PUBLIC HAS_YAML_CPP)
|
||||
else()
|
||||
message(STATUS "yaml-cpp not used")
|
||||
endif()
|
||||
|
||||
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
|
||||
AND NOT ${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD"
|
||||
AND NOT WIN32)
|
||||
@ -286,7 +296,10 @@ set(DROGON_SOURCES
|
||||
lib/src/SlidingWindowRateLimiter.cc
|
||||
lib/src/TokenBucketRateLimiter.cc
|
||||
lib/src/Hodor.cc
|
||||
lib/src/drogon_test.cc)
|
||||
lib/src/drogon_test.cc
|
||||
lib/src/ConfigAdapterManager.cc
|
||||
lib/src/JsonConfigAdapter.cc
|
||||
lib/src/YamlConfigAdapter.cc)
|
||||
set(private_headers
|
||||
lib/src/AOPAdvice.h
|
||||
lib/src/CacheFile.h
|
||||
@ -318,7 +331,11 @@ set(private_headers
|
||||
lib/src/WebsocketControllersRouter.h
|
||||
lib/src/FixedWindowRateLimiter.h
|
||||
lib/src/SlidingWindowRateLimiter.h
|
||||
lib/src/TokenBucketRateLimiter.h)
|
||||
lib/src/TokenBucketRateLimiter.h
|
||||
lib/src/ConfigAdapterManager.h
|
||||
lib/src/JsonConfigAdapter.h
|
||||
lib/src/YamlConfigAdapter.h
|
||||
lib/src/ConfigAdapter.h)
|
||||
|
||||
if (NOT WIN32)
|
||||
set(DROGON_SOURCES
|
||||
|
@ -40,6 +40,9 @@ endif()
|
||||
if(@Hiredis_FOUND@)
|
||||
find_dependency(Hiredis)
|
||||
endif()
|
||||
if(@yaml-cpp_FOUND)
|
||||
find_dependency(yaml-cpp)
|
||||
endif()
|
||||
if(@BUILD_SHARED_LIBS@)
|
||||
find_dependency(Threads)
|
||||
endif()
|
||||
@ -48,6 +51,7 @@ find_dependency(Filesystem)
|
||||
find_package(Filesystem COMPONENTS Final REQUIRED)
|
||||
endif()
|
||||
|
||||
|
||||
# Our library dependencies (contains definitions for IMPORTED targets)
|
||||
|
||||
get_filename_component(DROGON_CMAKE_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
|
||||
|
19
lib/src/ConfigAdapter.h
Normal file
19
lib/src/ConfigAdapter.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <json/json.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
class ConfigAdapter
|
||||
{
|
||||
public:
|
||||
virtual ~ConfigAdapter() = default;
|
||||
virtual Json::Value getJson(const std::string &configFile) const
|
||||
noexcept(false) = 0;
|
||||
virtual std::vector<std::string> getExtensions() const = 0;
|
||||
};
|
||||
using ConfigAdapterPtr = std::shared_ptr<ConfigAdapter>;
|
||||
|
||||
} // namespace drogon
|
46
lib/src/ConfigAdapterManager.cc
Normal file
46
lib/src/ConfigAdapterManager.cc
Normal file
@ -0,0 +1,46 @@
|
||||
#include "ConfigAdapterManager.h"
|
||||
#include "JsonConfigAdapter.h"
|
||||
#include "YamlConfigAdapter.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace drogon;
|
||||
#define REGISTER_CONFIG_ADAPTER(adapter) \
|
||||
{ \
|
||||
auto adapterPtr = std::make_shared<adapter>(); \
|
||||
auto exts = adapterPtr->getExtensions(); \
|
||||
for (auto ext : exts) \
|
||||
{ \
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); \
|
||||
adapters_[ext] = adapterPtr; \
|
||||
} \
|
||||
}
|
||||
ConfigAdapterManager &ConfigAdapterManager::instance()
|
||||
{
|
||||
static ConfigAdapterManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
Json::Value ConfigAdapterManager::getJson(const std::string &configFile) const
|
||||
noexcept(false)
|
||||
{
|
||||
auto pos = configFile.find_last_of('.');
|
||||
if (pos == std::string::npos)
|
||||
{
|
||||
throw std::runtime_error("Invalid config file name!");
|
||||
}
|
||||
auto ext = configFile.substr(pos + 1);
|
||||
// convert ext to lower case
|
||||
std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
|
||||
auto it = adapters_.find(ext);
|
||||
if (it == adapters_.end())
|
||||
{
|
||||
throw std::runtime_error("No valid parser for this config file!");
|
||||
}
|
||||
return it->second->getJson(configFile);
|
||||
}
|
||||
|
||||
ConfigAdapterManager::ConfigAdapterManager()
|
||||
{
|
||||
REGISTER_CONFIG_ADAPTER(JsonConfigAdapter);
|
||||
REGISTER_CONFIG_ADAPTER(YamlConfigAdapter);
|
||||
}
|
17
lib/src/ConfigAdapterManager.h
Normal file
17
lib/src/ConfigAdapterManager.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "ConfigAdapterManager.h"
|
||||
#include "ConfigAdapter.h"
|
||||
#include <map>
|
||||
namespace drogon
|
||||
{
|
||||
class ConfigAdapterManager
|
||||
{
|
||||
public:
|
||||
static ConfigAdapterManager &instance();
|
||||
Json::Value getJson(const std::string &configFile) const noexcept(false);
|
||||
|
||||
private:
|
||||
ConfigAdapterManager();
|
||||
std::map<std::string, ConfigAdapterPtr> adapters_;
|
||||
};
|
||||
} // namespace drogon
|
@ -33,7 +33,10 @@
|
||||
#define os_access access
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <drogon/utils/Utilities.h>
|
||||
#include "filesystem.h"
|
||||
#include "ConfigAdapterManager.h"
|
||||
|
||||
using namespace drogon;
|
||||
static bool bytesSize(std::string &sizeStr, size_t &size)
|
||||
@ -101,6 +104,7 @@ static bool bytesSize(std::string &sizeStr, size_t &size)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ConfigLoader::ConfigLoader(const std::string &configFile)
|
||||
{
|
||||
if (os_access(drogon::utils::toNativePath(configFile).c_str(), 0) != 0)
|
||||
@ -115,12 +119,8 @@ ConfigLoader::ConfigLoader(const std::string &configFile)
|
||||
configFile_ = configFile;
|
||||
try
|
||||
{
|
||||
std::ifstream infile(drogon::utils::toNativePath(configFile).c_str(),
|
||||
std::ifstream::in);
|
||||
if (infile)
|
||||
{
|
||||
infile >> configJsonRoot_;
|
||||
}
|
||||
auto filename = drogon::utils::toNativePath(configFile);
|
||||
configJsonRoot_ = ConfigAdapterManager::instance().getJson(configFile);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
|
21
lib/src/JsonConfigAdapter.cc
Normal file
21
lib/src/JsonConfigAdapter.cc
Normal file
@ -0,0 +1,21 @@
|
||||
#include "JsonConfigAdapter.h"
|
||||
#include <fstream>
|
||||
|
||||
using namespace drogon;
|
||||
Json::Value JsonConfigAdapter::getJson(const std::string &configFile) const
|
||||
noexcept(false)
|
||||
{
|
||||
Json::Value root;
|
||||
Json::Reader reader;
|
||||
std::ifstream in(configFile, std::ios::binary);
|
||||
if (!in.is_open())
|
||||
{
|
||||
throw std::runtime_error("Cannot open config file!");
|
||||
}
|
||||
in >> root;
|
||||
return root;
|
||||
}
|
||||
std::vector<std::string> JsonConfigAdapter::getExtensions() const
|
||||
{
|
||||
return {"json"};
|
||||
}
|
14
lib/src/JsonConfigAdapter.h
Normal file
14
lib/src/JsonConfigAdapter.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "ConfigAdapter.h"
|
||||
namespace drogon
|
||||
{
|
||||
class JsonConfigAdapter : public ConfigAdapter
|
||||
{
|
||||
public:
|
||||
JsonConfigAdapter() = default;
|
||||
~JsonConfigAdapter() override = default;
|
||||
Json::Value getJson(const std::string &configFile) const
|
||||
noexcept(false) override;
|
||||
std::vector<std::string> getExtensions() const override;
|
||||
};
|
||||
} // namespace drogon
|
118
lib/src/YamlConfigAdapter.cc
Normal file
118
lib/src/YamlConfigAdapter.cc
Normal file
@ -0,0 +1,118 @@
|
||||
#include "YamlConfigAdapter.h"
|
||||
#ifdef HAS_YAML_CPP
|
||||
#include <yaml-cpp/yaml.h>
|
||||
#endif
|
||||
using namespace drogon;
|
||||
#ifdef HAS_YAML_CPP
|
||||
namespace YAML
|
||||
{
|
||||
static bool yaml2json(const Node &node, Json::Value &jsonValue)
|
||||
{
|
||||
if (node.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (node.IsScalar())
|
||||
{
|
||||
if (node.Tag() != "!")
|
||||
{
|
||||
try
|
||||
{
|
||||
jsonValue = node.as<int64_t>();
|
||||
return true;
|
||||
}
|
||||
catch (const YAML::BadConversion &e)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
jsonValue = node.as<double>();
|
||||
return true;
|
||||
}
|
||||
catch (const YAML::BadConversion &e)
|
||||
{
|
||||
}
|
||||
try
|
||||
{
|
||||
jsonValue = node.as<bool>();
|
||||
return true;
|
||||
}
|
||||
catch (const YAML::BadConversion &e)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
Json::Value v(node.Scalar());
|
||||
jsonValue.swapPayload(v);
|
||||
return true;
|
||||
}
|
||||
else if (node.IsSequence())
|
||||
{
|
||||
for (std::size_t i = 0; i < node.size(); i++)
|
||||
{
|
||||
Json::Value v;
|
||||
if (yaml2json(node[i], v))
|
||||
{
|
||||
jsonValue.append(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (node.IsMap())
|
||||
{
|
||||
for (YAML::const_iterator it = node.begin(); it != node.end(); ++it)
|
||||
{
|
||||
Json::Value v;
|
||||
if (yaml2json(it->second, v))
|
||||
{
|
||||
jsonValue[it->first.Scalar()] = v;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct convert<Json::Value>
|
||||
{
|
||||
static bool decode(const Node &node, Json::Value &rhs)
|
||||
{
|
||||
return yaml2json(node, rhs);
|
||||
};
|
||||
};
|
||||
} // namespace YAML
|
||||
|
||||
#endif
|
||||
Json::Value YamlConfigAdapter::getJson(const std::string &configFile) const
|
||||
noexcept(false)
|
||||
{
|
||||
#if HAS_YAML_CPP
|
||||
// parse yaml file
|
||||
YAML::Node config = YAML::LoadFile(configFile);
|
||||
if (!config.IsNull())
|
||||
{
|
||||
return config.as<Json::Value>();
|
||||
}
|
||||
else
|
||||
return Json::Value();
|
||||
#else
|
||||
throw std::runtime_error("please install yaml-cpp library");
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<std::string> YamlConfigAdapter::getExtensions() const
|
||||
{
|
||||
return {"yaml", "yml"};
|
||||
}
|
14
lib/src/YamlConfigAdapter.h
Normal file
14
lib/src/YamlConfigAdapter.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "ConfigAdapter.h"
|
||||
namespace drogon
|
||||
{
|
||||
class YamlConfigAdapter : public ConfigAdapter
|
||||
{
|
||||
public:
|
||||
YamlConfigAdapter() = default;
|
||||
~YamlConfigAdapter() override = default;
|
||||
Json::Value getJson(const std::string &configFile) const
|
||||
noexcept(false) override;
|
||||
std::vector<std::string> getExtensions() const override;
|
||||
};
|
||||
} // namespace drogon
|
Loading…
Reference in New Issue
Block a user