mirror of
https://gitee.com/an-tao/drogon.git
synced 2024-12-01 19:27:53 +08:00
Make user can use a custom type parameter instead of the first parameter in handlers of HttpControllers (#284)
This commit is contained in:
parent
3a3a5636e8
commit
e7b6ba27bb
@ -68,7 +68,7 @@ int main()
|
||||
Drogon provides some interfaces for adding controller logic directly in the main() function, for example, user can register a handler like this in Drogon:
|
||||
|
||||
```c++
|
||||
app.registerHandler("/test?username={1}",
|
||||
app.registerHandler("/test?username={name}",
|
||||
[](const HttpRequestPtr& req,
|
||||
std::function<void (const HttpResponsePtr &)> &&callback,
|
||||
const std::string &name)
|
||||
@ -158,9 +158,9 @@ class User : public drogon::HttpController<User>
|
||||
public:
|
||||
METHOD_LIST_BEGIN
|
||||
//use METHOD_ADD to add your custom processing function here;
|
||||
METHOD_ADD(User::getInfo, "/{1}", Get); //path is /api/v1/User/{arg1}
|
||||
METHOD_ADD(User::getDetailInfo, "/{1}/detailinfo", Get); //path is /api/v1/User/{arg1}/detailinfo
|
||||
METHOD_ADD(User::newUser, "/{1}", Post); //path is /api/v1/User/{arg1}
|
||||
METHOD_ADD(User::getInfo, "/{id}", Get); //path is /api/v1/User/{arg1}
|
||||
METHOD_ADD(User::getDetailInfo, "/{id}/detailinfo", Get); //path is /api/v1/User/{arg1}/detailinfo
|
||||
METHOD_ADD(User::newUser, "/{name}", Post); //path is /api/v1/User/{arg1}
|
||||
METHOD_LIST_END
|
||||
//your declaration of processing function maybe like this:
|
||||
void getInfo(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback, int userId) const;
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
Drogon的主要应用平台是Linux,也支持Mac OS、FreeBSD,目前还不支持Windows。它的主要特点如下:
|
||||
|
||||
* 网络层使用基于epoll(MacOS/FreeBSD下是kqueue)的非阻塞IO框架,提供高并发、高性能的网络IO。详细请见[性能测试](https://github.com/an-tao/drogon/wiki/13-%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95);
|
||||
* 网络层使用基于epoll(MacOS/FreeBSD下是kqueue)的非阻塞IO框架,提供高并发、高性能的网络IO。详细请见[性能测试](https://github.com/an-tao/drogon/wiki/13-%E6%80%A7%E8%83%BD%E6%B5%8B%E8%AF%95)和[TFB Live Results](https://tfb-status.techempower.com/);
|
||||
* 全异步编程模式;
|
||||
* 支持Http1.0/1.1(server端和client端);
|
||||
* 基于template实现了简单的反射机制,使主程序框架、控制器(controller)和视图(view)完全解耦;
|
||||
|
@ -7,7 +7,7 @@ class CustomCtrl : public drogon::HttpController<CustomCtrl, false>
|
||||
METHOD_LIST_BEGIN
|
||||
// use METHOD_ADD to add your custom processing function here;
|
||||
METHOD_ADD(CustomCtrl::hello,
|
||||
"/{1}",
|
||||
"/{userName}",
|
||||
Get,
|
||||
"CustomHeaderFilter"); // path is /customctrl/{arg1}
|
||||
METHOD_LIST_END
|
||||
|
@ -374,9 +374,8 @@ void ApiTest::get2(const HttpRequestPtr &req,
|
||||
callback(res);
|
||||
}
|
||||
|
||||
void ApiTest::jsonTest(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
std::shared_ptr<Json::Value> &&json)
|
||||
void ApiTest::jsonTest(std::shared_ptr<Json::Value> &&json,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback)
|
||||
{
|
||||
Json::Value ret;
|
||||
if (json)
|
||||
|
@ -18,7 +18,7 @@ class ApiTest : public drogon::HttpController<ApiTest>
|
||||
"drogon::IntranetIpFilter");
|
||||
METHOD_ADD(ApiTest::rootPost, "", Post, Options);
|
||||
METHOD_ADD(ApiTest::get,
|
||||
"/get/{2:p2}/{1}",
|
||||
"/get/{2:p2}/{1:p1}",
|
||||
Get); // path is /api/v1/apitest/get/{arg2}/{arg1}
|
||||
METHOD_ADD(ApiTest::your_method_name,
|
||||
"/{PI}/List?P2={}",
|
||||
@ -26,10 +26,10 @@ class ApiTest : public drogon::HttpController<ApiTest>
|
||||
METHOD_ADD(ApiTest::staticApi, "/static", Get, Options); // CORS
|
||||
METHOD_ADD(ApiTest::staticApi, "/static", Post, Put, Delete);
|
||||
METHOD_ADD(ApiTest::get2,
|
||||
"/get/{1}",
|
||||
"/get/{}",
|
||||
Get); // path is /api/v1/apitest/get/{arg1}
|
||||
ADD_METHOD_TO(ApiTest::get2,
|
||||
"/absolute/{1}",
|
||||
"/absolute/{}",
|
||||
Get); // path is /absolute/{arg1}
|
||||
METHOD_ADD(ApiTest::jsonTest, "/json", Post);
|
||||
METHOD_ADD(ApiTest::formTest, "/form", Post);
|
||||
@ -54,9 +54,8 @@ class ApiTest : public drogon::HttpController<ApiTest>
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
void rootPost(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
void jsonTest(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
std::shared_ptr<Json::Value> &&json);
|
||||
void jsonTest(std::shared_ptr<Json::Value> &&json,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
void formTest(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback);
|
||||
void attributesTest(
|
||||
|
@ -122,7 +122,7 @@ using namespace drogon;
|
||||
namespace drogon
|
||||
{
|
||||
template <>
|
||||
string_view fromRequest<string_view>(const HttpRequest &req)
|
||||
string_view fromRequest(const HttpRequest &req)
|
||||
{
|
||||
return req.body();
|
||||
}
|
||||
@ -143,12 +143,13 @@ int main()
|
||||
.addListener("0.0.0.0", 8849, true);
|
||||
}
|
||||
// Class function example
|
||||
app().registerHandler("/api/v1/handle1/{1}/{2}/?p3={3}&p4={4}", &A::handle);
|
||||
app().registerHandler("/api/v1/handle11/{1}/{2}/?p3={3}&p4={4}",
|
||||
&A::staticHandle);
|
||||
app().registerHandler("/api/v1/handle1/{}/{}/?p3={}&p4={}", &A::handle);
|
||||
app().registerHandler(
|
||||
"/api/v1/handle11/{int p1}/{string p2}/?p3={string p3}&p4={int p4}",
|
||||
&A::staticHandle);
|
||||
// Lambda example
|
||||
app().registerHandler(
|
||||
"/api/v1/handle2/{1}/{2}",
|
||||
"/api/v1/handle2/{int a}/{float b}",
|
||||
[](const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
int a, // here the `a` parameter is converted from the number 1
|
||||
@ -186,7 +187,7 @@ int main()
|
||||
const std::string &,
|
||||
int)>
|
||||
func = std::bind(&A::handle, &tmp, _1, _2, _3, _4, _5, _6);
|
||||
app().registerHandler("/api/v1/handle4/{4}/{3}/{1}", func);
|
||||
app().registerHandler("/api/v1/handle4/{4:p4}/{3:p3}/{1:p1}", func);
|
||||
|
||||
app().setDocumentRoot("./");
|
||||
app().enableSession(60);
|
||||
|
@ -273,8 +273,11 @@ class HttpBinder : public HttpBinderBase
|
||||
}
|
||||
template <typename... Values,
|
||||
bool isClassFunction = traits::isClassFunction,
|
||||
bool isDrObjectClass = traits::isDrObjectClass>
|
||||
typename std::enable_if<isClassFunction && !isDrObjectClass, void>::type
|
||||
bool isDrObjectClass = traits::isDrObjectClass,
|
||||
bool isNormal = std::is_same<typename traits::first_param_type,
|
||||
HttpRequestPtr>::value>
|
||||
typename std::enable_if<isClassFunction && !isDrObjectClass && isNormal,
|
||||
void>::type
|
||||
callFunction(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Values &&... values)
|
||||
@ -284,8 +287,11 @@ class HttpBinder : public HttpBinderBase
|
||||
}
|
||||
template <typename... Values,
|
||||
bool isClassFunction = traits::isClassFunction,
|
||||
bool isDrObjectClass = traits::isDrObjectClass>
|
||||
typename std::enable_if<isClassFunction && isDrObjectClass, void>::type
|
||||
bool isDrObjectClass = traits::isDrObjectClass,
|
||||
bool isNormal = std::is_same<typename traits::first_param_type,
|
||||
HttpRequestPtr>::value>
|
||||
typename std::enable_if<isClassFunction && isDrObjectClass && isNormal,
|
||||
void>::type
|
||||
callFunction(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Values &&... values)
|
||||
@ -295,14 +301,58 @@ class HttpBinder : public HttpBinderBase
|
||||
(*objPtr.*_func)(req, std::move(callback), std::move(values)...);
|
||||
}
|
||||
template <typename... Values,
|
||||
bool isClassFunction = traits::isClassFunction>
|
||||
typename std::enable_if<!isClassFunction, void>::type callFunction(
|
||||
const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Values &&... values)
|
||||
bool isClassFunction = traits::isClassFunction,
|
||||
bool isNormal = std::is_same<typename traits::first_param_type,
|
||||
HttpRequestPtr>::value>
|
||||
typename std::enable_if<!isClassFunction && isNormal, void>::type
|
||||
callFunction(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Values &&... values)
|
||||
{
|
||||
_func(req, std::move(callback), std::move(values)...);
|
||||
}
|
||||
////////////////////////////////////////////////////////////////
|
||||
template <typename... Values,
|
||||
bool isClassFunction = traits::isClassFunction,
|
||||
bool isDrObjectClass = traits::isDrObjectClass,
|
||||
bool isNormal = std::is_same<typename traits::first_param_type,
|
||||
HttpRequestPtr>::value>
|
||||
typename std::enable_if<isClassFunction && !isDrObjectClass && !isNormal,
|
||||
void>::type
|
||||
callFunction(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Values &&... values)
|
||||
{
|
||||
static auto &obj = getControllerObj<typename traits::class_type>();
|
||||
(obj.*_func)((*req), std::move(callback), std::move(values)...);
|
||||
}
|
||||
template <typename... Values,
|
||||
bool isClassFunction = traits::isClassFunction,
|
||||
bool isDrObjectClass = traits::isDrObjectClass,
|
||||
bool isNormal = std::is_same<typename traits::first_param_type,
|
||||
HttpRequestPtr>::value>
|
||||
typename std::enable_if<isClassFunction && isDrObjectClass && !isNormal,
|
||||
void>::type
|
||||
callFunction(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Values &&... values)
|
||||
{
|
||||
static auto objPtr =
|
||||
DrClassMap::getSingleInstance<typename traits::class_type>();
|
||||
(*objPtr.*_func)((*req), std::move(callback), std::move(values)...);
|
||||
}
|
||||
template <typename... Values,
|
||||
bool isClassFunction = traits::isClassFunction,
|
||||
bool isNormal = std::is_same<typename traits::first_param_type,
|
||||
HttpRequestPtr>::value>
|
||||
typename std::enable_if<!isClassFunction && !isNormal, void>::type
|
||||
callFunction(const HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Values &&... values)
|
||||
{
|
||||
_func((*req), std::move(callback), std::move(values)...);
|
||||
}
|
||||
/////////////
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
@ -85,6 +85,39 @@ struct FunctionTraits<
|
||||
{
|
||||
static const bool isHTTPFunction = true;
|
||||
typedef void class_type;
|
||||
typedef HttpRequestPtr first_param_type;
|
||||
};
|
||||
|
||||
template <typename ReturnType, typename... Arguments>
|
||||
struct FunctionTraits<
|
||||
ReturnType (*)(HttpRequestPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Arguments...)> : FunctionTraits<ReturnType (*)(Arguments...)>
|
||||
{
|
||||
static const bool isHTTPFunction = false;
|
||||
typedef void class_type;
|
||||
};
|
||||
|
||||
template <typename ReturnType, typename... Arguments>
|
||||
struct FunctionTraits<
|
||||
ReturnType (*)(HttpRequestPtr &&req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Arguments...)> : FunctionTraits<ReturnType (*)(Arguments...)>
|
||||
{
|
||||
static const bool isHTTPFunction = false;
|
||||
typedef void class_type;
|
||||
};
|
||||
|
||||
// normal function for HTTP handling
|
||||
template <typename T, typename ReturnType, typename... Arguments>
|
||||
struct FunctionTraits<
|
||||
ReturnType (*)(T &&customReq,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
Arguments...)> : FunctionTraits<ReturnType (*)(Arguments...)>
|
||||
{
|
||||
static const bool isHTTPFunction = true;
|
||||
typedef void class_type;
|
||||
typedef T first_param_type;
|
||||
};
|
||||
|
||||
// normal function
|
||||
|
Loading…
Reference in New Issue
Block a user