mirror of
https://github.com/CrowCpp/Crow.git
synced 2024-06-07 21:10:44 +00:00
Added basic blueprint support (registration and prefix)
This commit is contained in:
parent
a8e55b7a09
commit
c46af69f41
@ -73,6 +73,10 @@ else ()
|
|||||||
target_compile_options(example_json_map PRIVATE "${compiler_options}")
|
target_compile_options(example_json_map PRIVATE "${compiler_options}")
|
||||||
target_link_libraries(example_json_map PUBLIC ${REQUIRED_LIBRARIES})
|
target_link_libraries(example_json_map PUBLIC ${REQUIRED_LIBRARIES})
|
||||||
|
|
||||||
|
add_executable(example_blueprint example_blueprint.cpp)
|
||||||
|
target_compile_options(example_blueprint PRIVATE "${compiler_options}")
|
||||||
|
target_link_libraries(example_blueprint PUBLIC ${REQUIRED_LIBRARIES})
|
||||||
|
|
||||||
add_custom_command(OUTPUT example_chat.html
|
add_custom_command(OUTPUT example_chat.html
|
||||||
COMMAND ${CMAKE_COMMAND} -E
|
COMMAND ${CMAKE_COMMAND} -E
|
||||||
copy ${PROJECT_SOURCE_DIR}/example_chat.html ${CMAKE_CURRENT_BINARY_DIR}/example_chat.html
|
copy ${PROJECT_SOURCE_DIR}/example_chat.html ${CMAKE_CURRENT_BINARY_DIR}/example_chat.html
|
||||||
|
18
examples/example_blueprint.cpp
Normal file
18
examples/example_blueprint.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#define CROW_MAIN
|
||||||
|
#include "crow.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
crow::SimpleApp app;
|
||||||
|
|
||||||
|
crow::Blueprint bp("bp_prefix");
|
||||||
|
|
||||||
|
CROW_BP_ROUTE(app, bp, "/")
|
||||||
|
([]() {
|
||||||
|
return "Hello world!";
|
||||||
|
});
|
||||||
|
|
||||||
|
app.register_blueprint(bp);
|
||||||
|
|
||||||
|
app.port(18080).run();
|
||||||
|
}
|
@ -24,8 +24,10 @@
|
|||||||
|
|
||||||
#ifdef CROW_MSVC_WORKAROUND
|
#ifdef CROW_MSVC_WORKAROUND
|
||||||
#define CROW_ROUTE(app, url) app.route_dynamic(url)
|
#define CROW_ROUTE(app, url) app.route_dynamic(url)
|
||||||
|
#define CROW_BP_ROUTE(app, blueprint, url) app.route_dynamic(blueprint, url)
|
||||||
#else
|
#else
|
||||||
#define CROW_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url)
|
#define CROW_ROUTE(app, url) app.route<crow::black_magic::get_parameter_tag(url)>(url)
|
||||||
|
#define CROW_BP_ROUTE(app, blueprint, url) app.route<crow::black_magic::get_parameter_tag(url)>(blueprint, url)
|
||||||
#endif
|
#endif
|
||||||
#define CROW_CATCHALL_ROUTE(app) app.catchall_route()
|
#define CROW_CATCHALL_ROUTE(app) app.catchall_route()
|
||||||
|
|
||||||
@ -80,14 +82,28 @@ namespace crow
|
|||||||
return router_.new_rule_dynamic(std::move(rule));
|
return router_.new_rule_dynamic(std::move(rule));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Create a dynamic route for a blueprint using a rule (**Use CROW_ROUTE instead**)
|
||||||
|
DynamicRule& route_dynamic(Blueprint& blueprint, std::string&& rule)
|
||||||
|
{
|
||||||
|
return blueprint.new_rule_dynamic(std::move(rule));
|
||||||
|
}
|
||||||
|
|
||||||
///Create a route using a rule (**Use CROW_ROUTE instead**)
|
///Create a route using a rule (**Use CROW_ROUTE instead**)
|
||||||
template <uint64_t Tag>
|
template <uint64_t Tag>
|
||||||
auto route(std::string&& rule)
|
auto route(std::string&& rule)
|
||||||
-> typename std::result_of<decltype(&Router::new_rule_tagged<Tag>)(Router, std::string&&)>::type
|
-> typename std::result_of<decltype(&Router::new_rule_tagged<Tag>)(Router, std::string&&)>::type
|
||||||
{
|
{//TODO process the blueprint
|
||||||
return router_.new_rule_tagged<Tag>(std::move(rule));
|
return router_.new_rule_tagged<Tag>(std::move(rule));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///Create a route for a blueprint using a rule (**Use CROW_ROUTE instead**)
|
||||||
|
template <uint64_t Tag>
|
||||||
|
auto route(Blueprint& blueprint, std::string&& rule)
|
||||||
|
-> typename std::result_of<decltype(&Router::new_rule_tagged<Tag>)(Router, std::string&&)>::type
|
||||||
|
{
|
||||||
|
return blueprint.new_rule_tagged<Tag>(std::move(rule));
|
||||||
|
}
|
||||||
|
|
||||||
///Create a route for any requests without a proper route (**Use CROW_CATCHALL_ROUTE instead**)
|
///Create a route for any requests without a proper route (**Use CROW_CATCHALL_ROUTE instead**)
|
||||||
CatchallRule& catchall_route()
|
CatchallRule& catchall_route()
|
||||||
{
|
{
|
||||||
@ -158,12 +174,21 @@ namespace crow
|
|||||||
/// crow::LogLevel::Warning (2)<br>
|
/// crow::LogLevel::Warning (2)<br>
|
||||||
/// crow::LogLevel::Error (3)<br>
|
/// crow::LogLevel::Error (3)<br>
|
||||||
/// crow::LogLevel::Critical (4)<br>
|
/// crow::LogLevel::Critical (4)<br>
|
||||||
self_t& loglevel(crow::LogLevel level)
|
self_t& loglevel(LogLevel level)
|
||||||
{
|
{
|
||||||
crow::logger::setLogLevel(level);
|
crow::logger::setLogLevel(level);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self_t& register_blueprint(Blueprint& blueprint)
|
||||||
|
{
|
||||||
|
if (blueprints_.empty() || std::find(blueprints_.begin(), blueprints_.end(), &blueprint) == blueprints_.end())
|
||||||
|
{
|
||||||
|
blueprints_.emplace_back(&blueprint);
|
||||||
|
}//TODO error throwing
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
///Set a custom duration and function to run on every tick
|
///Set a custom duration and function to run on every tick
|
||||||
template <typename Duration, typename Func>
|
template <typename Duration, typename Func>
|
||||||
self_t& tick(Duration d, Func f) {
|
self_t& tick(Duration d, Func f) {
|
||||||
@ -191,7 +216,7 @@ namespace crow
|
|||||||
///Go through the rules, upgrade them if possible, and add them to the list of rules
|
///Go through the rules, upgrade them if possible, and add them to the list of rules
|
||||||
void validate()
|
void validate()
|
||||||
{
|
{
|
||||||
router_.validate();
|
router_.validate(blueprints_);
|
||||||
}
|
}
|
||||||
|
|
||||||
///Notify anything using `wait_for_server_start()` to proceed
|
///Notify anything using `wait_for_server_start()` to proceed
|
||||||
@ -380,6 +405,8 @@ namespace crow
|
|||||||
|
|
||||||
std::vector<int> signals_{SIGINT, SIGTERM};
|
std::vector<int> signals_{SIGINT, SIGTERM};
|
||||||
|
|
||||||
|
std::vector<Blueprint*> blueprints_;
|
||||||
|
|
||||||
bool server_started_{false};
|
bool server_started_{false};
|
||||||
std::condition_variable cv_started_;
|
std::condition_variable cv_started_;
|
||||||
std::mutex start_mutex_;
|
std::mutex start_mutex_;
|
||||||
|
@ -1029,6 +1029,94 @@ namespace crow
|
|||||||
std::vector<Node> nodes_;
|
std::vector<Node> nodes_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A blueprint can be considered a smaller section of a Crow app, specifically where the router is conecerned.
|
||||||
|
class Blueprint
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Blueprint()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Blueprint(const std::string& prefix):
|
||||||
|
prefix_(prefix){};
|
||||||
|
|
||||||
|
Blueprint(std::string&& prefix):
|
||||||
|
prefix_(prefix){};
|
||||||
|
/*
|
||||||
|
Blueprint(Blueprint& other)
|
||||||
|
{
|
||||||
|
prefix_ = std::move(other.prefix_);
|
||||||
|
all_rules_ = std::move(other.all_rules_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Blueprint(const Blueprint& other)
|
||||||
|
{
|
||||||
|
prefix_ = other.prefix_;
|
||||||
|
all_rules_ = other.all_rules_;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
Blueprint(Blueprint&& value)
|
||||||
|
{
|
||||||
|
*this = std::move(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
Blueprint& operator = (const Blueprint& value) = delete;
|
||||||
|
|
||||||
|
Blueprint& operator = (Blueprint&& value) noexcept
|
||||||
|
{
|
||||||
|
prefix_ = std::move(value.prefix_);
|
||||||
|
all_rules_ = std::move(value.all_rules_);
|
||||||
|
catchall_rule_ = std::move(value.catchall_rule_);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator == (const Blueprint& value)
|
||||||
|
{
|
||||||
|
return value.prefix() == prefix_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator != (const Blueprint& value)
|
||||||
|
{
|
||||||
|
return value.prefix() != prefix_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string prefix() const
|
||||||
|
{
|
||||||
|
return prefix_;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicRule& new_rule_dynamic(const std::string& rule)
|
||||||
|
{
|
||||||
|
std::string new_rule = '/' + prefix_ + rule;
|
||||||
|
auto ruleObject = new DynamicRule(new_rule);
|
||||||
|
all_rules_.emplace_back(ruleObject);
|
||||||
|
|
||||||
|
return *ruleObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <uint64_t N>
|
||||||
|
typename black_magic::arguments<N>::type::template rebind<TaggedRule>& new_rule_tagged(const std::string& rule)
|
||||||
|
{
|
||||||
|
std::string new_rule = '/' + prefix_ + rule;
|
||||||
|
using RuleT = typename black_magic::arguments<N>::type::template rebind<TaggedRule>;
|
||||||
|
|
||||||
|
auto ruleObject = new RuleT(new_rule);
|
||||||
|
all_rules_.emplace_back(ruleObject);
|
||||||
|
|
||||||
|
return *ruleObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
CatchallRule& catchall_rule()
|
||||||
|
{
|
||||||
|
return catchall_rule_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string prefix_;
|
||||||
|
std::vector<std::unique_ptr<BaseRule>> all_rules_;
|
||||||
|
CatchallRule catchall_rule_;
|
||||||
|
friend class Router;
|
||||||
|
};
|
||||||
|
|
||||||
/// Handles matching requests to existing rules and upgrade requests.
|
/// Handles matching requests to existing rules and upgrade requests.
|
||||||
class Router
|
class Router
|
||||||
@ -1088,8 +1176,20 @@ namespace crow
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void validate()
|
void validate(std::vector<Blueprint*>& bp_list)
|
||||||
{
|
{
|
||||||
|
//Take all the routes from the registered blueprints and add them to `all_rules_` to be processed.
|
||||||
|
if (!(bp_list.empty()))
|
||||||
|
{
|
||||||
|
for (Blueprint* bp : bp_list)
|
||||||
|
{
|
||||||
|
for (auto& rule: bp->all_rules_)
|
||||||
|
{
|
||||||
|
all_rules_.push_back(std::move(rule));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(auto& rule:all_rules_)
|
for(auto& rule:all_rules_)
|
||||||
{
|
{
|
||||||
if (rule)
|
if (rule)
|
||||||
|
Loading…
Reference in New Issue
Block a user