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:
}
};
namespace Generic {
void handleReady(const Rest::Request&, Http::Response response) {
response.send(Http::Code::Ok, "1");
}
}
class StatsEndpoint {
public:
StatsEndpoint(Net::Address addr)
: httpEndpoint(addr)
: httpEndpoint(std::make_shared<Net::Http::Endpoint>(addr))
, monitor(httpEndpoint)
{ }
void init() {
auto opts = Net::Http::Endpoint::options()
.threads(1)
.flags(Net::Tcp::Options::InstallSignalHandler);
httpEndpoint.init(opts);
httpEndpoint->init(opts);
setupRoutes();
monitor.setInterval(std::chrono::seconds(5));
}
void start() {
httpEndpoint.setHandler(router.handler());
httpEndpoint.serve();
monitor.start();
httpEndpoint->setHandler(router.handler());
httpEndpoint->serve();
}
void shutdown() {
httpEndpoint.shutdown();
httpEndpoint->shutdown();
monitor.shutdown();
}
private:
void setupRoutes() {
using namespace Net::Rest;
Routes::Post(router, "/record/:name/:value?", &StatsEndpoint::doRecordMetric, this);
Routes::Get(router, "/value/:name", &StatsEndpoint::doGetMetric, this);
Routes::Post(router, "/record/:name/:value?", Routes::bind(&StatsEndpoint::doRecordMetric, 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) {
......@@ -236,8 +250,9 @@ private:
std::vector<Metric> metrics;
Net::Http::Endpoint httpEndpoint;
std::shared_ptr<Net::Http::Endpoint> httpEndpoint;
Rest::Router router;
LoadMonitor monitor;
};
int main(int argc, char *argv[]) {
......
......@@ -7,6 +7,7 @@
#pragma once
#include <string>
#include <tuple>
#include "http.h"
#include "http_defs.h"
#include "flags.h"
......@@ -187,24 +188,52 @@ namespace Routes {
void Put(Router& router, std::string resource, Route::Handler handler);
void Delete(Router& router, std::string resource, Route::Handler handler);
template<typename Handler, typename Obj>
void Get(Router& router, std::string resource, Handler handler, Obj obj) {
Get(router, std::move(resource), std::bind(handler, obj, std::placeholders::_1, std::placeholders::_2));
}
namespace details {
template <class... Args>
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>
void Post(Router& router, std::string resource, Handler handler, Obj obj) {
Post(router, std::move(resource), std::bind(handler, obj, std::placeholders::_1, std::placeholders::_2));
template<typename... Args>
void static_checks() {
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) {
Put(router, std::move(resource), std::bind(handler, obj, std::placeholders::_1, std::placeholders::_2));
template<typename Result, typename Cls, typename... Args, typename Obj>
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>
void Delete(Router& router, std::string resource, Handler handler, Obj obj) {
Delete(router, std::move(resource), std::bind(handler, obj, std::placeholders::_1, std::placeholders::_2));
template<typename Result, typename... Args>
Route::Handler bind(Result (*func)(Args...)) {
details::static_checks<Args...>();
return [=](const Rest::Request& request, Http::Response response) {
func(request, std::move(response));
};
}
} // 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