#pragma once #include "ApiTypes.h" namespace resource_api { // a base class for routing requests to handler methods // nothing is thread safe here class ResourceRouter { public: virtual ~ResourceRouter(); // can return NULL, if the request was processed // if the Response can not be created immediately, // then return a object which implements the ResponseTask interface ResponseTask* handleRequest(Request& req, Response& resp); template void addResourceHandler(std::string name, T* instance, ResponseTask* (T::*callback)(Request& req, Response& resp)); template void addResourceHandler(std::string name, T* instance, void (T::*callback)(Request& req, Response& resp)); private: class HandlerBase { public: virtual ~HandlerBase(){} virtual ResponseTask* handleRequest(Request& req, Response& resp) = 0; }; template class Handler: public HandlerBase { public: virtual ResponseTask* handleRequest(Request &req, Response &resp) { return (instance->*method)(req, resp); } T* instance; ResponseTask* (T::*method)(Request& req, Response& resp); }; template class InstantResponseHandler: public HandlerBase { public: virtual ResponseTask* handleRequest(Request &req, Response &resp) { (instance->*method)(req, resp); return 0; } T* instance; void (T::*method)(Request& req, Response& resp); }; std::vector > mHandlers; }; // the advantage of this approach is: // the method name is arbitrary, one class can have many different handler methods // with raw objects the name of the handler method would be fixed, and we would need one class for every handler // the downside is complicated template magic template void ResourceRouter::addResourceHandler(std::string name, T* instance, ResponseTask* (T::*callback)(Request& req, Response& resp)) { Handler* handler = new Handler(); handler->instance = instance; handler->method = callback; mHandlers.push_back(std::make_pair(name, handler)); } template void ResourceRouter::addResourceHandler(std::string name, T* instance, void (T::*callback)(Request& req, Response& resp)) { InstantResponseHandler* handler = new InstantResponseHandler(); handler->instance = instance; handler->method = callback; mHandlers.push_back(std::make_pair(name, handler)); } } // namespace resource_api