Commit fa382599 authored by octal's avatar octal

A route can now be bound to a non member function. Also changed the API a...

A route can now be bound to a non member function. Also changed the API a litle bit to avoid big code duplication
parent a64024b5
...@@ -139,35 +139,49 @@ private: ...@@ -139,35 +139,49 @@ private:
} }
}; };
namespace Generic {
void handleReady(const Rest::Request&, Http::Response response) {
response.send(Http::Code::Ok, "1");
}
}
class StatsEndpoint { class StatsEndpoint {
public: public:
StatsEndpoint(Net::Address addr) StatsEndpoint(Net::Address addr)
: httpEndpoint(addr) : httpEndpoint(std::make_shared<Net::Http::Endpoint>(addr))
, monitor(httpEndpoint)
{ } { }
void init() { void init() {
auto opts = Net::Http::Endpoint::options() auto opts = Net::Http::Endpoint::options()
.threads(1) .threads(1)
.flags(Net::Tcp::Options::InstallSignalHandler); .flags(Net::Tcp::Options::InstallSignalHandler);
httpEndpoint.init(opts); httpEndpoint->init(opts);
setupRoutes(); setupRoutes();
monitor.setInterval(std::chrono::seconds(5));
} }
void start() { void start() {
httpEndpoint.setHandler(router.handler()); monitor.start();
httpEndpoint.serve(); httpEndpoint->setHandler(router.handler());
httpEndpoint->serve();
} }
void shutdown() { void shutdown() {
httpEndpoint.shutdown(); httpEndpoint->shutdown();
monitor.shutdown();
} }
private: private:
void setupRoutes() { void setupRoutes() {
using namespace Net::Rest; using namespace Net::Rest;
Routes::Post(router, "/record/:name/:value?", &StatsEndpoint::doRecordMetric, this); Routes::Post(router, "/record/:name/:value?", Routes::bind(&StatsEndpoint::doRecordMetric, this));
Routes::Get(router, "/value/:name", &StatsEndpoint::doGetMetric, this); Routes::Get(router, "/value/:name", Routes::bind(&StatsEndpoint::doGetMetric, this));
Routes::Get(router, "/ready", Routes::bind(&Generic::handleReady));
} }
void doRecordMetric(const Rest::Request& request, Net::Http::Response response) { void doRecordMetric(const Rest::Request& request, Net::Http::Response response) {
...@@ -236,8 +250,9 @@ private: ...@@ -236,8 +250,9 @@ private:
std::vector<Metric> metrics; std::vector<Metric> metrics;
Net::Http::Endpoint httpEndpoint; std::shared_ptr<Net::Http::Endpoint> httpEndpoint;
Rest::Router router; Rest::Router router;
LoadMonitor monitor;
}; };
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <tuple>
#include "http.h" #include "http.h"
#include "http_defs.h" #include "http_defs.h"
#include "flags.h" #include "flags.h"
...@@ -187,24 +188,52 @@ namespace Routes { ...@@ -187,24 +188,52 @@ namespace Routes {
void Put(Router& router, std::string resource, Route::Handler handler); void Put(Router& router, std::string resource, Route::Handler handler);
void Delete(Router& router, std::string resource, Route::Handler handler); void Delete(Router& router, std::string resource, Route::Handler handler);
template<typename Handler, typename Obj> namespace details {
void Get(Router& router, std::string resource, Handler handler, Obj obj) { template <class... Args>
Get(router, std::move(resource), std::bind(handler, obj, std::placeholders::_1, std::placeholders::_2)); struct TypeList
} {
template<size_t N>
struct At {
static_assert(N < sizeof...(Args), "Invalid index");
typedef typename std::tuple_element<N, std::tuple<Args...>>::type Type;
};
};
template<typename Handler, typename Obj> template<typename... Args>
void Post(Router& router, std::string resource, Handler handler, Obj obj) { void static_checks() {
Post(router, std::move(resource), std::bind(handler, obj, std::placeholders::_1, std::placeholders::_2)); static_assert(sizeof...(Args) == 2, "Function should take 2 parameters");
typedef details::TypeList<Args...> Arguments;
// Disabled now as it
// 1/ does not compile
// 2/ might not be relevant
#if 0
static_assert(std::is_same<Arguments::At<0>::Type, const Rest::Request&>::value, "First argument should be a const Rest::Request&");
static_assert(std::is_same<typename Arguments::At<0>::Type, Http::Response>::value, "Second argument should be a Http::Response");
#endif
}
} }
template<typename Handler, typename Obj>
void Put(Router& router, std::string resource, Handler handler, Obj obj) { template<typename Result, typename Cls, typename... Args, typename Obj>
Put(router, std::move(resource), std::bind(handler, obj, std::placeholders::_1, std::placeholders::_2)); Route::Handler bind(Result (Cls::*func)(Args...), Obj obj) {
details::static_checks<Args...>();
#define CALL_MEMBER_FN(obj, pmf) ((obj)->*(pmf))
return [=](const Rest::Request& request, Http::Response response) {
CALL_MEMBER_FN(obj, func)(request, std::move(response));
};
#undef CALL_MEMBER_FN
} }
template<typename Handler, typename Obj> template<typename Result, typename... Args>
void Delete(Router& router, std::string resource, Handler handler, Obj obj) { Route::Handler bind(Result (*func)(Args...)) {
Delete(router, std::move(resource), std::bind(handler, obj, std::placeholders::_1, std::placeholders::_2)); details::static_checks<Args...>();
return [=](const Rest::Request& request, Http::Response response) {
func(request, std::move(response));
};
} }
} // namespace Routing } // namespace Routing
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment