make HttpApiBinder support lambda and std::function

This commit is contained in:
an-tao 2018-06-04 23:45:21 +08:00
parent a8bc891209
commit ed4ed3fda0
4 changed files with 82 additions and 10 deletions

View File

@ -1,7 +1,6 @@
#include <iostream>
#include <drogon/HttpAppFramework.h>
#include <trantor/utils/Logger.h>
#include <drogon/HttpApiBinder.h>
#include <vector>
#include <string>
using namespace drogon;
@ -16,18 +15,27 @@ public:
LOG_DEBUG<<"int haha="<<haha;
}
};
using namespace std::placeholders;
int main()
{
std::cout<<banner<<std::endl;
auto bindPtr=std::make_shared<drogon::HttpApiBinder<decltype(&A::handle)>>(&A::handle);
//drogon::HttpApiBinder<A, decltype(&A::handle)> binder(&A::handle);
// binder.test();
drogon::HttpAppFramework::instance().addListener("0.0.0.0",12345);
drogon::HttpAppFramework::instance().addListener("0.0.0.0",8080);
trantor::Logger::setLogLevel(trantor::Logger::TRACE);
drogon::HttpAppFramework::instance().registerHttpApiController("/api/v1","",bindPtr);
drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle1","",&A::handle);
drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle2","",[](const HttpRequest&req,std::function<void (HttpResponse &)>callback,int a,float b){
LOG_DEBUG<<"int a="<<a;
LOG_DEBUG<<"flaot b="<<b;
});
// A tmp;
// std::function<void(const HttpRequest&,std::function<void (HttpResponse &)>,int,const std::string &,const std::string &,int)>
// func();
// drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle3","",std::bind(&A::handle,&tmp,_1,_2,_3,_4,_5,_6));
drogon::HttpAppFramework::instance().run();
}

View File

@ -36,13 +36,14 @@ namespace drogon{
class HttpApiBinder:public HttpApiBinderBase
{
public:
typedef FUNCTION FunctionType;
virtual void handleHttpApiRequest(std::list<std::string> &pathParameter,
const HttpRequest& req,std::function<void (HttpResponse &)>callback) override
{
run(pathParameter,req,callback);
}
HttpApiBinder(FUNCTION func):
_func(func)
HttpApiBinder(FUNCTION &&func):
_func(std::forward<FUNCTION>(func))
{
static_assert(traits::isHTTPApiFunction,"Your API handler function interface is wrong!");
}
@ -93,10 +94,26 @@ namespace drogon{
const HttpRequest& req,std::function<void (HttpResponse &)>callback,
Values&&... values
)
{
callFunction(req,callback,std::move(values)...);
}
template <typename... Values,
bool isClassFunction = traits::isClassFunction>
typename std::enable_if<isClassFunction,void>::type callFunction(
const HttpRequest& req,std::function<void (HttpResponse &)>callback,
Values&&... values)
{
//new object per time or create a object in constructor???
std::unique_ptr<typename traits::class_type> ptr(new typename traits::class_type);
(ptr.get()->*_func)(req,callback,std::move(values)...);
}
};
template <typename... Values,
bool isClassFunction = traits::isClassFunction>
typename std::enable_if<!isClassFunction,void>::type callFunction(
const HttpRequest& req,std::function<void (HttpResponse &)>callback,
Values&&... values)
{
_func(req,callback,std::move(values)...);
};
};
}

View File

@ -60,6 +60,29 @@ namespace drogon
const std::string &parameterPattern,
const HttpApiBinderBasePtr &binder,
const std::vector<std::string> &filters=std::vector<std::string>())=0;
template <typename FUNCTION>
static void registerHttpApiMethod(const std::string &pathName,
const std::string &parameterPattern,
FUNCTION && function,
const std::vector<std::string> &filters=std::vector<std::string>())
{
static_assert(!std::is_bind_expression<FUNCTION>::value);
HttpApiBinderBasePtr binder=std::make_shared<
HttpApiBinder<FUNCTION>
>(std::forward<FUNCTION>(function));
instance().registerHttpApiController(pathName,parameterPattern,binder,filters);
}
// template <typename FUNCTION>
// static void registerHttpApiBind(const std::string &pathName,
// const std::string &parameterPattern,
// const std::function<FUNCTION> & function,
// const std::vector<std::string> &filters=std::vector<std::string>())
// {
// HttpApiBinderBasePtr binder=std::make_shared<
// HttpApiBinder<decltype(function)>
// >(std::forward<decltype(function)>(function));
// instance().registerHttpApiController(pathName,parameterPattern,binder,filters);
// }
virtual void enableSession(const size_t timeout=0)=0;
virtual void disableSession()=0;
};

View File

@ -34,9 +34,10 @@ namespace drogon{
ReturnType(ClassType::*)(Arguments...)
> : FunctionTraits<ReturnType(*)(Arguments...)> {
static const bool isClassFunction=true;
typedef ClassType class_type;
};
//class function
template <
typename ClassType,
typename ReturnType,
@ -44,10 +45,32 @@ namespace drogon{
>
struct FunctionTraits<
ReturnType(ClassType::*)(const HttpRequest& req,std::function<void (HttpResponse &)>callback,Arguments...)
> : FunctionTraits<ReturnType(ClassType::*)(Arguments...)> {
static const bool isHTTPApiFunction=true;
};
//std::function
template <
typename ReturnType,
typename... Arguments
>
struct FunctionTraits<
ReturnType(*)(const HttpRequest& req,std::function<void (HttpResponse &)>callback,Arguments...)
> : FunctionTraits<ReturnType(*)(Arguments...)> {
static const bool isHTTPApiFunction=true;
typedef ClassType class_type;
};
};
//normal function
template <
typename ReturnType,
typename... Arguments
>
struct FunctionTraits<std::function<
ReturnType(const HttpRequest& req,std::function<void (HttpResponse &)>callback,Arguments...)>>
:FunctionTraits<ReturnType(*)(Arguments...)> {
static const bool isHTTPApiFunction=true;
};
template <
typename ReturnType,
@ -67,6 +90,7 @@ namespace drogon{
static const std::size_t arity = sizeof...(Arguments);
static const bool isHTTPApiFunction=false;
static const bool isClassFunction=false;
};
}