mirror of
https://github.com/drogonframework/drogon.git
synced 2025-09-14 00:00:48 -04:00
Add support for AOP
This commit is contained in:
parent
c1b5a240cb
commit
1bc07c5197
@ -32,6 +32,8 @@ Drogon's main application platform is Linux. It also supports Mac OS and FreeBSD
|
||||
* Support asynchronously reading and writing sqlite3 database based on thread pool;
|
||||
* Support ARM Architecture;
|
||||
* Provide a convenient lightweight ORM implementation that supports for regular object-to-database bidirectional mapping;
|
||||
* Support plugins which can be installed by the configuration file at load time;
|
||||
* Support AOP with build-in joinpoints.
|
||||
|
||||
## A very simple example
|
||||
|
||||
|
@ -32,5 +32,7 @@ Drogon的主要应用平台是Linux,也支持Mac OS、FreeBSD,目前还不
|
||||
* 基于线程池实现sqlite3数据库的异步读写,提供与上文数据库相同的接口;
|
||||
* 支持ARM架构;
|
||||
* 方便的轻量级ORM实现,支持常规的对象到数据库的双向映射操作;
|
||||
* 支持插件,可通过配置文件在加载期动态拆装;
|
||||
* 支持内建插入点的AOP
|
||||
|
||||
### 更多详情请浏览 [wiki](https://gitee.com/an-tao/drogon/wikis/概述)
|
@ -9,7 +9,7 @@ using namespace drogon;
|
||||
using namespace std::chrono_literals;
|
||||
class A : public DrObjectBase
|
||||
{
|
||||
public:
|
||||
public:
|
||||
void handle(const HttpRequestPtr &req,
|
||||
const std::function<void(const HttpResponsePtr &)> &callback,
|
||||
int p1, const std::string &p2, const std::string &p3, int p4) const
|
||||
@ -45,7 +45,7 @@ class A : public DrObjectBase
|
||||
};
|
||||
class B : public DrObjectBase
|
||||
{
|
||||
public:
|
||||
public:
|
||||
void operator()(const HttpRequestPtr &req, const std::function<void(const HttpResponsePtr &)> &callback, int p1, int p2)
|
||||
{
|
||||
HttpViewData data;
|
||||
@ -64,7 +64,7 @@ namespace v1
|
||||
{
|
||||
class Test : public HttpController<Test>
|
||||
{
|
||||
public:
|
||||
public:
|
||||
METHOD_LIST_BEGIN
|
||||
METHOD_ADD(Test::get, "get/{2}/{1}", Get); //path is /api/v1/test/get/{arg2}/{arg1}
|
||||
METHOD_ADD(Test::list, "/{2}/info", Get); //path is /api/v1/test/{arg2}/info
|
||||
@ -155,5 +155,47 @@ int main()
|
||||
auto filterPtr = std::make_shared<CustomHeaderFilter>("custom_header", "yes");
|
||||
app().registerFilter(filterPtr);
|
||||
app().setIdleConnectionTimeout(30s);
|
||||
//Test AOP
|
||||
app().registerBeginningAdvice([]() {
|
||||
LOG_DEBUG << "Event loop is running!";
|
||||
});
|
||||
app().registerNewConnectionAdvice([](const trantor::InetAddress &peer, const trantor::InetAddress &local) {
|
||||
LOG_DEBUG << "New connection: " << peer.toIpPort() << "-->" << local.toIpPort();
|
||||
return true;
|
||||
});
|
||||
app().registerPreRoutingAdvice([](const drogon::HttpRequestPtr &req,
|
||||
const drogon::AdviceCallback &acb,
|
||||
const drogon::AdviceChainCallback &accb) {
|
||||
LOG_DEBUG << "preRouting1";
|
||||
accb();
|
||||
});
|
||||
app().registerPostRoutingAdvice([](const drogon::HttpRequestPtr &req,
|
||||
const drogon::AdviceCallback &acb,
|
||||
const drogon::AdviceChainCallback &accb) {
|
||||
LOG_DEBUG << "postRouting1";
|
||||
LOG_DEBUG << "Matched path=" << req->matchedPathPattern();
|
||||
accb();
|
||||
});
|
||||
app().registerPreHandlingAdvice([](const drogon::HttpRequestPtr &req,
|
||||
const drogon::AdviceCallback &acb,
|
||||
const drogon::AdviceChainCallback &accb) {
|
||||
LOG_DEBUG << "preHandling1";
|
||||
// auto resp = HttpResponse::newNotFoundResponse();
|
||||
// acb(resp);
|
||||
// return;
|
||||
accb();
|
||||
});
|
||||
app().registerPostHandlingAdvice([](const drogon::HttpRequestPtr &, const drogon::HttpResponsePtr &) {
|
||||
LOG_DEBUG << "postHandling1";
|
||||
});
|
||||
app().registerPreRoutingAdvice([](const drogon::HttpRequestPtr &req) {
|
||||
LOG_DEBUG << "preRouting observer";
|
||||
});
|
||||
app().registerPostRoutingAdvice([](const drogon::HttpRequestPtr &req) {
|
||||
LOG_DEBUG << "postRouting observer";
|
||||
});
|
||||
app().registerPreHandlingAdvice([](const drogon::HttpRequestPtr &req) {
|
||||
LOG_DEBUG << "preHanding observer";
|
||||
});
|
||||
app().run();
|
||||
}
|
||||
|
@ -63,6 +63,8 @@ inline std::string getGitCommit()
|
||||
class HttpControllerBase;
|
||||
class HttpSimpleControllerBase;
|
||||
class WebSocketControllerBase;
|
||||
typedef std::function<void(const HttpResponsePtr &)> AdviceCallback;
|
||||
typedef std::function<void()> AdviceChainCallback;
|
||||
|
||||
class HttpAppFramework : public trantor::NonCopyable
|
||||
{
|
||||
@ -121,7 +123,7 @@ class HttpAppFramework : public trantor::NonCopyable
|
||||
/**
|
||||
* NOTE:
|
||||
* This method is usually called after the framework is run.
|
||||
* Calling this method in the initAndStart() method of some plugins is also valid.
|
||||
* Calling this method in the initAndStart() method of plugins is also valid.
|
||||
*/
|
||||
template <typename T>
|
||||
T *getPlugin()
|
||||
@ -137,10 +139,75 @@ class HttpAppFramework : public trantor::NonCopyable
|
||||
*
|
||||
* NOTE:
|
||||
* This method is usually called after the framework is run.
|
||||
* Calling this method in the initAndStart() method of some plugins is also valid.
|
||||
* Calling this method in the initAndStart() method of plugins is also valid.
|
||||
*/
|
||||
virtual PluginBase *getPlugin(const std::string &name) = 0;
|
||||
|
||||
///The following is a series of methods of AOP
|
||||
|
||||
///The @param advice is called immediately after the main event loop runs.
|
||||
virtual void registerBeginningAdvice(const std::function<void()> &advice) = 0;
|
||||
|
||||
///The @param advice is called immediately when a new connection is established.
|
||||
/**
|
||||
* The first parameter of the @param advice is the remote address of the new connection, the second one
|
||||
* is the local address of it.
|
||||
* If the @param advice returns a false value, drogon closes the connection.
|
||||
* Users can use this advice to implement some security policies.
|
||||
*/
|
||||
virtual void registerNewConnectionAdvice(const std::function<bool(const trantor::InetAddress &, const trantor::InetAddress &)> &advice) = 0;
|
||||
|
||||
///The @param advice is called immediately after the request is created and before it matches any handler paths.
|
||||
/**
|
||||
* The parameters of the @param advice are same as those of the doFilter method of the Filter class.
|
||||
*/
|
||||
virtual void registerPreRoutingAdvice(const std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)> &advice) = 0;
|
||||
|
||||
///The @param advice is called at the same time as the above advice. It can be thought of as an observer who cannot respond to http requests.
|
||||
/**
|
||||
* This advice has less overhead than the above one.
|
||||
* If one does not intend to intercept the http request, please use this interface.
|
||||
*/
|
||||
virtual void registerPreRoutingAdvice(const std::function<void(const HttpRequestPtr &)> &advice) = 0;
|
||||
|
||||
///The @param advice is called immediately after the request matchs a handler path
|
||||
///and before any 'doFilter' method of filters applies.
|
||||
/**
|
||||
* The parameters of the @param advice are same as those of the doFilter method of the Filter class.
|
||||
*/
|
||||
virtual void registerPostRoutingAdvice(const std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)> &advice) = 0;
|
||||
|
||||
///The @param advice is called at the same time as the above advice. It can be thought of as an observer who cannot respond to http requests.
|
||||
/**
|
||||
* This advice has less overhead than the above one.
|
||||
* If one does not intend to intercept the http request, please use this interface.
|
||||
*/
|
||||
virtual void registerPostRoutingAdvice(const std::function<void(const HttpRequestPtr &)> &advice) = 0;
|
||||
|
||||
///The @param advice is called immediately after the request is approved by all filters and before it is handled.
|
||||
/**
|
||||
* The parameters of the @param advice are same as those of the doFilter method of the Filter class.
|
||||
*/
|
||||
virtual void registerPreHandlingAdvice(const std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)> &advice) = 0;
|
||||
|
||||
///The @param advice is called at the same time as the above advice. It can be thought of as an observer who cannot respond to http requests.
|
||||
/**
|
||||
* This advice has less overhead than the above one.
|
||||
* If one does not intend to intercept the http request, please use this interface.
|
||||
*/
|
||||
virtual void registerPreHandlingAdvice(const std::function<void(const HttpRequestPtr &)> &advice) = 0;
|
||||
|
||||
///The @param advice is called immediately after the request is handled and a response object is created by handlers or by filters.
|
||||
virtual void registerPostHandlingAdvice(const std::function<void(const HttpRequestPtr &, const HttpResponsePtr &)> &advice) = 0;
|
||||
|
||||
///End of AOP methods
|
||||
|
||||
///Load the configuration file with json format.
|
||||
virtual void loadConfigFile(const std::string &fileName) = 0;
|
||||
|
||||
|
@ -23,11 +23,20 @@
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
typedef std::function<void(HttpResponsePtr)> FilterCallback;
|
||||
typedef std::function<void(const HttpResponsePtr &)> FilterCallback;
|
||||
typedef std::function<void()> FilterChainCallback;
|
||||
class HttpFilterBase : public virtual DrObjectBase
|
||||
{
|
||||
public:
|
||||
public:
|
||||
/// This virtual function should be overrided in subclasses.
|
||||
/**
|
||||
* This method is an asynchronous interface, user should return the result via 'FilterCallback'
|
||||
* or 'FilterChainCallback'.
|
||||
* If @param fcb is called, the response object is send to the client by the callback,
|
||||
* and doFilter methods of next filters and the handler registed on the path are not called anymore.
|
||||
* If @param fccb is called, the next filter's doFilter method or the handler
|
||||
* registered on the path is called.
|
||||
*/
|
||||
virtual void doFilter(const HttpRequestPtr &req,
|
||||
const FilterCallback &fcb,
|
||||
const FilterChainCallback &fccb) = 0;
|
||||
@ -36,7 +45,7 @@ class HttpFilterBase : public virtual DrObjectBase
|
||||
template <typename T, bool AutoCreation = true>
|
||||
class HttpFilter : public DrObject<T>, public HttpFilterBase
|
||||
{
|
||||
public:
|
||||
public:
|
||||
static const bool isAutoCreation = AutoCreation;
|
||||
virtual ~HttpFilter() {}
|
||||
};
|
||||
|
53
lib/src/AOPAdvice.cc
Normal file
53
lib/src/AOPAdvice.cc
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
#include "AOPAdvice.h"
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
|
||||
void doAdvicesChain(const std::vector<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>> &advices,
|
||||
size_t index,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
std::function<void()> &&missCallback)
|
||||
{
|
||||
if (index < advices.size())
|
||||
{
|
||||
auto &advice = advices[index];
|
||||
advice(req,
|
||||
*callbackPtr,
|
||||
[index, req, callbackPtr, &advices, missCallback = std::move(missCallback)]() mutable {
|
||||
doAdvicesChain(advices, index + 1, req, callbackPtr, std::move(missCallback));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
missCallback();
|
||||
}
|
||||
}
|
||||
|
||||
void doAdvicesChain(const std::deque<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>> &advices,
|
||||
size_t index,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
std::function<void()> &&missCallback)
|
||||
{
|
||||
if (index < advices.size())
|
||||
{
|
||||
auto &advice = advices[index];
|
||||
advice(req,
|
||||
*callbackPtr,
|
||||
[index, req, callbackPtr, &advices, missCallback = std::move(missCallback)]() mutable {
|
||||
doAdvicesChain(advices, index + 1, req, callbackPtr, std::move(missCallback));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
missCallback();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace drogon
|
35
lib/src/AOPAdvice.h
Normal file
35
lib/src/AOPAdvice.h
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
*
|
||||
* AOPAdvice.h
|
||||
* An Tao
|
||||
*
|
||||
* Copyright 2018, An Tao. All rights reserved.
|
||||
* https://github.com/an-tao/drogon
|
||||
* Use of this source code is governed by a MIT license
|
||||
* that can be found in the License file.
|
||||
*
|
||||
* Drogon
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "HttpRequestImpl.h"
|
||||
#include <drogon/HttpAppFramework.h>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
void doAdvicesChain(const std::vector<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>> &advices,
|
||||
size_t index,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
std::function<void()> &&missCallback);
|
||||
void doAdvicesChain(const std::deque<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>> &advices,
|
||||
size_t index,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
std::function<void()> &&missCallback);
|
||||
} // namespace drogon
|
@ -18,22 +18,24 @@
|
||||
|
||||
#include <queue>
|
||||
|
||||
using namespace drogon;
|
||||
|
||||
static void doFilterChains(const std::vector<std::shared_ptr<HttpFilterBase>> &filters,
|
||||
size_t index,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
bool needSetJsessionid,
|
||||
const std::shared_ptr<std::string> &sessionIdPtr,
|
||||
std::function<void()> &&missCallback)
|
||||
namespace drogon
|
||||
{
|
||||
namespace FiltersFunction
|
||||
{
|
||||
|
||||
static void doFilterChains(const std::vector<std::shared_ptr<HttpFilterBase>> &filters,
|
||||
size_t index,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
bool needSetJsessionid,
|
||||
const std::shared_ptr<std::string> &sessionIdPtr,
|
||||
std::function<void()> &&missCallback)
|
||||
{
|
||||
if (index < filters.size())
|
||||
{
|
||||
auto &filter = filters[index];
|
||||
filter->doFilter(req,
|
||||
[=](HttpResponsePtr res) {
|
||||
[needSetJsessionid, callbackPtr, sessionIdPtr](const HttpResponsePtr &res) {
|
||||
if (needSetJsessionid)
|
||||
res->addCookie("JSESSIONID", *sessionIdPtr);
|
||||
(*callbackPtr)(res);
|
||||
@ -48,7 +50,7 @@ static void doFilterChains(const std::vector<std::shared_ptr<HttpFilterBase>> &f
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> FiltersFunction::createFilters(const std::vector<std::string> &filterNames)
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> createFilters(const std::vector<std::string> &filterNames)
|
||||
{
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> filters;
|
||||
for (auto const &filter : filterNames)
|
||||
@ -65,13 +67,16 @@ std::vector<std::shared_ptr<HttpFilterBase>> FiltersFunction::createFilters(cons
|
||||
return filters;
|
||||
}
|
||||
|
||||
void FiltersFunction::doFilters(const std::vector<std::shared_ptr<HttpFilterBase>> &filters,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
bool needSetJsessionid,
|
||||
const std::shared_ptr<std::string> &sessionIdPtr,
|
||||
std::function<void()> &&missCallback)
|
||||
void doFilters(const std::vector<std::shared_ptr<HttpFilterBase>> &filters,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
bool needSetJsessionid,
|
||||
const std::shared_ptr<std::string> &sessionIdPtr,
|
||||
std::function<void()> &&missCallback)
|
||||
{
|
||||
|
||||
doFilterChains(filters, 0, req, callbackPtr, needSetJsessionid, sessionIdPtr, std::move(missCallback));
|
||||
}
|
||||
|
||||
} // namespace FiltersFunction
|
||||
} // namespace drogon
|
@ -22,16 +22,16 @@
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
|
||||
struct FiltersFunction
|
||||
namespace FiltersFunction
|
||||
{
|
||||
static std::vector<std::shared_ptr<HttpFilterBase>> createFilters(const std::vector<std::string> &filterNames);
|
||||
static void doFilters(const std::vector<std::shared_ptr<HttpFilterBase>> &filters,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
bool needSetJsessionid,
|
||||
const std::shared_ptr<std::string> &sessionIdPtr,
|
||||
std::function<void()> &&missCallback);
|
||||
};
|
||||
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> createFilters(const std::vector<std::string> &filterNames);
|
||||
void doFilters(const std::vector<std::shared_ptr<HttpFilterBase>> &filters,
|
||||
const HttpRequestImplPtr &req,
|
||||
const std::shared_ptr<const std::function<void(const HttpResponsePtr &)>> &callbackPtr,
|
||||
bool needSetJsessionid,
|
||||
const std::shared_ptr<std::string> &sessionIdPtr,
|
||||
std::function<void()> &&missCallback);
|
||||
|
||||
} // namespace FiltersFunction
|
||||
} // namespace drogon
|
@ -15,6 +15,7 @@
|
||||
#include "HttpAppFrameworkImpl.h"
|
||||
#include "ConfigLoader.h"
|
||||
#include "HttpServer.h"
|
||||
#include "AOPAdvice.h"
|
||||
#if USE_ORM
|
||||
#include "../../orm_lib/src/DbClientLockFree.h"
|
||||
#endif
|
||||
@ -479,6 +480,7 @@ void HttpAppFrameworkImpl::onConnection(const TcpConnectionPtr &conn)
|
||||
{
|
||||
LOG_ERROR << "too much connections!force close!";
|
||||
conn->forceClose();
|
||||
return;
|
||||
}
|
||||
else if (_maxConnectionNumPerIP > 0)
|
||||
{
|
||||
@ -494,9 +496,18 @@ void HttpAppFrameworkImpl::onConnection(const TcpConnectionPtr &conn)
|
||||
conn->getLoop()->queueInLoop([conn]() {
|
||||
conn->forceClose();
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto &advice : _newConnectionAdvices)
|
||||
{
|
||||
if (!advice(conn->peerAddr(), conn->localAddr()))
|
||||
{
|
||||
conn->forceClose();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -720,7 +731,74 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
|
||||
}
|
||||
|
||||
//Route to controller
|
||||
_httpSimpleCtrlsRouter.route(req, std::move(callback), needSetJsessionid, std::move(sessionId));
|
||||
if (!_preRoutingObservers.empty())
|
||||
{
|
||||
for (auto &observer : _preRoutingObservers)
|
||||
{
|
||||
observer(req);
|
||||
}
|
||||
}
|
||||
if (_postHandlingAdvices.empty())
|
||||
{
|
||||
if (_preRoutingAdvices.empty())
|
||||
{
|
||||
_httpSimpleCtrlsRouter.route(req, std::move(callback), needSetJsessionid, std::move(sessionId));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
doAdvicesChain(_preRoutingAdvices,
|
||||
0,
|
||||
req,
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>([callbackPtr, needSetJsessionid, sessionIdPtr](const HttpResponsePtr &resp) {
|
||||
if (!needSetJsessionid)
|
||||
(*callbackPtr)(resp);
|
||||
else
|
||||
{
|
||||
resp->addCookie("JSESSIONID", *sessionIdPtr);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
}),
|
||||
[this, callbackPtr, req, needSetJsessionid, sessionIdPtr]() {
|
||||
_httpSimpleCtrlsRouter.route(req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto postHandlingCallback = [this, req, callback = std::move(callback)](const HttpResponsePtr &resp) -> void {
|
||||
for (auto &advice : _postHandlingAdvices)
|
||||
{
|
||||
advice(req, resp);
|
||||
}
|
||||
callback(resp);
|
||||
};
|
||||
if (_preRoutingAdvices.empty())
|
||||
{
|
||||
_httpSimpleCtrlsRouter.route(req, std::move(postHandlingCallback), needSetJsessionid, std::move(sessionId));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(postHandlingCallback));
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
doAdvicesChain(_preRoutingAdvices,
|
||||
0,
|
||||
req,
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>([callbackPtr, needSetJsessionid, sessionIdPtr](const HttpResponsePtr &resp) {
|
||||
if (!needSetJsessionid)
|
||||
(*callbackPtr)(resp);
|
||||
else
|
||||
{
|
||||
resp->addCookie("JSESSIONID", *sessionIdPtr);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
}),
|
||||
[this, callbackPtr, req, needSetJsessionid, sessionIdPtr]() mutable {
|
||||
_httpSimpleCtrlsRouter.route(req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trantor::EventLoop *HttpAppFrameworkImpl::getLoop()
|
||||
|
@ -18,9 +18,9 @@
|
||||
#include "HttpResponseImpl.h"
|
||||
#include "HttpClientImpl.h"
|
||||
#include "SharedLibManager.h"
|
||||
#include "WebSocketConnectionImpl.h"
|
||||
#include "HttpControllersRouter.h"
|
||||
#include "HttpSimpleControllersRouter.h"
|
||||
#include "WebSocketConnectionImpl.h"
|
||||
#include "WebsocketControllersRouter.h"
|
||||
#include "PluginsManager.h"
|
||||
|
||||
@ -47,14 +47,15 @@ struct InitBeforeMainFunction
|
||||
};
|
||||
class HttpAppFrameworkImpl : public HttpAppFramework
|
||||
{
|
||||
public:
|
||||
public:
|
||||
HttpAppFrameworkImpl()
|
||||
: _httpSimpleCtrlsRouter(_httpCtrlsRouter),
|
||||
: _httpCtrlsRouter(_postRoutingAdvices, _postRoutingObservers, _preHandlingAdvices, _preHandlingObservers),
|
||||
_httpSimpleCtrlsRouter(_httpCtrlsRouter, _postRoutingAdvices, _postRoutingObservers, _preHandlingAdvices, _preHandlingObservers),
|
||||
_uploadPath(_rootPath + "uploads"),
|
||||
_connectionNum(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual const Json::Value &getCustomConfig() const override
|
||||
{
|
||||
return _jsonConfig["custom_config"];
|
||||
@ -93,6 +94,53 @@ class HttpAppFrameworkImpl : public HttpAppFramework
|
||||
{
|
||||
return _custom404;
|
||||
}
|
||||
|
||||
virtual void registerBeginningAdvice(const std::function<void()> &advice) override
|
||||
{
|
||||
getLoop()->runInLoop(advice);
|
||||
}
|
||||
|
||||
virtual void registerNewConnectionAdvice(const std::function<bool(const trantor::InetAddress &, const trantor::InetAddress &)> &advice) override
|
||||
{
|
||||
_newConnectionAdvices.emplace_back(advice);
|
||||
}
|
||||
|
||||
virtual void registerPreRoutingAdvice(const std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)> &advice) override
|
||||
{
|
||||
_preRoutingAdvices.emplace_back(advice);
|
||||
}
|
||||
virtual void registerPostRoutingAdvice(const std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)> &advice) override
|
||||
{
|
||||
_postRoutingAdvices.emplace_front(advice);
|
||||
}
|
||||
virtual void registerPreHandlingAdvice(const std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)> &advice) override
|
||||
{
|
||||
_preHandlingAdvices.emplace_back(advice);
|
||||
}
|
||||
|
||||
virtual void registerPreRoutingAdvice(const std::function<void(const HttpRequestPtr &)> &advice) override
|
||||
{
|
||||
_preRoutingObservers.emplace_back(advice);
|
||||
}
|
||||
virtual void registerPostRoutingAdvice(const std::function<void(const HttpRequestPtr &)> &advice) override
|
||||
{
|
||||
_postRoutingObservers.emplace_front(advice);
|
||||
}
|
||||
virtual void registerPreHandlingAdvice(const std::function<void(const HttpRequestPtr &)> &advice) override
|
||||
{
|
||||
_preHandlingObservers.emplace_back(advice);
|
||||
}
|
||||
virtual void registerPostHandlingAdvice(const std::function<void(const HttpRequestPtr &, const HttpResponsePtr &)> &advice) override
|
||||
{
|
||||
_postHandlingAdvices.emplace_front(advice);
|
||||
}
|
||||
|
||||
virtual void enableSession(const size_t timeout = 0) override
|
||||
{
|
||||
_useSession = true;
|
||||
@ -179,7 +227,7 @@ class HttpAppFrameworkImpl : public HttpAppFramework
|
||||
}
|
||||
bool useSendfile() { return _useSendfile; }
|
||||
|
||||
private:
|
||||
private:
|
||||
virtual void registerHttpController(const std::string &pathPattern,
|
||||
const internal::HttpBinderBasePtr &binder,
|
||||
const std::vector<HttpMethod> &validMethods = std::vector<HttpMethod>(),
|
||||
@ -264,6 +312,26 @@ class HttpAppFrameworkImpl : public HttpAppFramework
|
||||
void createDbClients(const std::vector<trantor::EventLoop *> &ioloops);
|
||||
#endif
|
||||
static InitBeforeMainFunction _initFirst;
|
||||
std::vector<std::function<bool(const trantor::InetAddress &, const trantor::InetAddress &)>> _newConnectionAdvices;
|
||||
std::vector<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>>
|
||||
_preRoutingAdvices;
|
||||
std::deque<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>>
|
||||
_postRoutingAdvices;
|
||||
std::vector<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>>
|
||||
_preHandlingAdvices;
|
||||
std::deque<std::function<void(const HttpRequestPtr &,
|
||||
const HttpResponsePtr &)>>
|
||||
_postHandlingAdvices;
|
||||
|
||||
std::vector<std::function<void(const HttpRequestPtr &)>> _preRoutingObservers;
|
||||
std::deque<std::function<void(const HttpRequestPtr &)>> _postRoutingObservers;
|
||||
std::vector<std::function<void(const HttpRequestPtr &)>> _preHandlingObservers;
|
||||
};
|
||||
|
||||
} // namespace drogon
|
||||
|
@ -193,18 +193,50 @@ void HttpControllersRouter::route(const HttpRequestImplPtr &req,
|
||||
callback(res);
|
||||
return;
|
||||
}
|
||||
if (!binder->_filters.empty())
|
||||
if (!_postRoutingObservers.empty())
|
||||
{
|
||||
auto &filters = binder->_filters;
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
|
||||
FiltersFunction::doFilters(filters, req, callbackPtr, needSetJsessionid, sessionIdPtr, [=, &binder, &routerItem]() {
|
||||
doControllerHandler(binder, routerItem, req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
for (auto &observer : _postRoutingObservers)
|
||||
{
|
||||
observer(req);
|
||||
}
|
||||
}
|
||||
if (_postRoutingAdvices.empty())
|
||||
{
|
||||
if (!binder->_filters.empty())
|
||||
{
|
||||
auto &filters = binder->_filters;
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
|
||||
FiltersFunction::doFilters(filters, req, callbackPtr, needSetJsessionid, sessionIdPtr, [=, &binder, &routerItem]() {
|
||||
doPreHandlingAdvices(binder, routerItem, req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
doPreHandlingAdvices(binder, routerItem, req, std::move(callback), needSetJsessionid, std::move(sessionId));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
doControllerHandler(binder, routerItem, req, std::move(callback), needSetJsessionid, std::move(sessionId));
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
|
||||
doAdvicesChain(_postRoutingAdvices,
|
||||
0,
|
||||
req,
|
||||
callbackPtr,
|
||||
[&binder, sessionId = std::move(sessionId), callbackPtr, req, needSetJsessionid, this, &routerItem]() mutable {
|
||||
if (!binder->_filters.empty())
|
||||
{
|
||||
auto &filters = binder->_filters;
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
FiltersFunction::doFilters(filters, req, callbackPtr, needSetJsessionid, sessionIdPtr, [=, &binder, &routerItem]() {
|
||||
doPreHandlingAdvices(binder, routerItem, req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
doPreHandlingAdvices(binder, routerItem, req, std::move(*callbackPtr), needSetJsessionid, std::move(sessionId));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -280,7 +312,7 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> params(ctrlBinderPtr->_parameterPlaces.size());
|
||||
std::smatch r;
|
||||
if (std::regex_match(req->path(), r, routerItem._regex))
|
||||
@ -347,4 +379,44 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
|
||||
callback(newResp);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
void HttpControllersRouter::doPreHandlingAdvices(const CtrlBinderPtr &ctrlBinderPtr,
|
||||
const HttpControllerRouterItem &routerItem,
|
||||
const HttpRequestImplPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId)
|
||||
{
|
||||
if (!_preHandlingObservers.empty())
|
||||
{
|
||||
for (auto &observer : _preHandlingObservers)
|
||||
{
|
||||
observer(req);
|
||||
}
|
||||
}
|
||||
if (_preHandlingAdvices.empty())
|
||||
{
|
||||
doControllerHandler(ctrlBinderPtr, routerItem, req, std::move(callback), needSetJsessionid, std::move(sessionId));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
doAdvicesChain(_preHandlingAdvices,
|
||||
0,
|
||||
req,
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>([callbackPtr, needSetJsessionid, sessionIdPtr](const HttpResponsePtr &resp) {
|
||||
if (!needSetJsessionid)
|
||||
(*callbackPtr)(resp);
|
||||
else
|
||||
{
|
||||
resp->addCookie("JSESSIONID", *sessionIdPtr);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
}),
|
||||
[this, ctrlBinderPtr, &routerItem, req, callbackPtr, needSetJsessionid, sessionIdPtr]() {
|
||||
doControllerHandler(ctrlBinderPtr, routerItem, req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
#pragma once
|
||||
#include "HttpRequestImpl.h"
|
||||
#include "HttpResponseImpl.h"
|
||||
#include "AOPAdvice.h"
|
||||
#include <trantor/utils/NonCopyable.h>
|
||||
#include <drogon/HttpBinder.h>
|
||||
#include <drogon/HttpFilter.h>
|
||||
@ -27,11 +28,27 @@
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
class HttpAppFrameworkImpl;
|
||||
class HttpControllersRouter : public trantor::NonCopyable
|
||||
{
|
||||
public:
|
||||
HttpControllersRouter() {}
|
||||
public:
|
||||
HttpControllersRouter(const std::deque<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>>
|
||||
&postRoutingAdvices,
|
||||
const std::deque<std::function<void(const HttpRequestPtr &)>>
|
||||
&postRoutingObservers,
|
||||
const std::vector<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>>
|
||||
&preHandlingAdvices,
|
||||
const std::vector<std::function<void(const HttpRequestPtr &)>>
|
||||
&preHandlingObservers)
|
||||
: _postRoutingAdvices(postRoutingAdvices),
|
||||
_preHandlingAdvices(preHandlingAdvices),
|
||||
_postRoutingObservers(postRoutingObservers),
|
||||
_preHandlingObservers(preHandlingObservers)
|
||||
{
|
||||
}
|
||||
void init(const std::vector<trantor::EventLoop *> &ioLoops);
|
||||
void addHttpPath(const std::string &path,
|
||||
const internal::HttpBinderBasePtr &binder,
|
||||
@ -42,7 +59,7 @@ class HttpControllersRouter : public trantor::NonCopyable
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId);
|
||||
|
||||
private:
|
||||
private:
|
||||
struct CtrlBinder
|
||||
{
|
||||
internal::HttpBinderBasePtr _binderPtr;
|
||||
@ -50,7 +67,7 @@ class HttpControllersRouter : public trantor::NonCopyable
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> _filters;
|
||||
std::vector<size_t> _parameterPlaces;
|
||||
std::map<std::string, size_t> _queryParametersPlaces;
|
||||
std::map<trantor::EventLoop *,std::shared_ptr<HttpResponse>> _responsePtrMap;
|
||||
std::map<trantor::EventLoop *, std::shared_ptr<HttpResponse>> _responsePtrMap;
|
||||
bool _isCORS = false;
|
||||
};
|
||||
typedef std::shared_ptr<CtrlBinder> CtrlBinderPtr;
|
||||
@ -59,12 +76,29 @@ class HttpControllersRouter : public trantor::NonCopyable
|
||||
std::string _pathParameterPattern;
|
||||
std::string _pathPattern;
|
||||
std::regex _regex;
|
||||
CtrlBinderPtr _binders[Invalid]={nullptr}; //The enum value Invalid is the http methods number
|
||||
CtrlBinderPtr _binders[Invalid] = {nullptr}; //The enum value Invalid is the http methods number
|
||||
};
|
||||
std::vector<HttpControllerRouterItem> _ctrlVector;
|
||||
std::mutex _ctrlMutex;
|
||||
std::regex _ctrlRegex;
|
||||
|
||||
const std::deque<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>> &_postRoutingAdvices;
|
||||
const std::vector<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>> &_preHandlingAdvices;
|
||||
const std::deque<std::function<void(const HttpRequestPtr &)>>
|
||||
&_postRoutingObservers;
|
||||
const std::vector<std::function<void(const HttpRequestPtr &)>>
|
||||
&_preHandlingObservers;
|
||||
void doPreHandlingAdvices(const CtrlBinderPtr &ctrlBinderPtr,
|
||||
const HttpControllerRouterItem &routerItem,
|
||||
const HttpRequestImplPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId);
|
||||
|
||||
void doControllerHandler(const CtrlBinderPtr &ctrlBinderPtr,
|
||||
const HttpControllerRouterItem &routerItem,
|
||||
const HttpRequestImplPtr &req,
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "FiltersFunction.h"
|
||||
#include "HttpSimpleControllersRouter.h"
|
||||
#include "HttpAppFrameworkImpl.h"
|
||||
#include "AOPAdvice.h"
|
||||
|
||||
using namespace drogon;
|
||||
|
||||
@ -91,6 +92,7 @@ void HttpSimpleControllersRouter::route(const HttpRequestImplPtr &req,
|
||||
if (iter != _simpCtrlMap.end())
|
||||
{
|
||||
auto &ctrlInfo = iter->second;
|
||||
req->setMatchedPathPattern(pathLower);
|
||||
auto &binder = ctrlInfo._binders[req->method()];
|
||||
if (!binder)
|
||||
{
|
||||
@ -107,18 +109,52 @@ void HttpSimpleControllersRouter::route(const HttpRequestImplPtr &req,
|
||||
callback(res);
|
||||
return;
|
||||
}
|
||||
auto &filters = ctrlInfo._binders[req->method()]->_filters;
|
||||
if (!filters.empty())
|
||||
//Do post routing advices.
|
||||
if (!_postRoutingObservers.empty())
|
||||
{
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
|
||||
FiltersFunction::doFilters(filters, req, callbackPtr, needSetJsessionid, sessionIdPtr, [=, &binder]() mutable {
|
||||
doControllerHandler(binder, ctrlInfo, req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
for (auto &observer : _postRoutingObservers)
|
||||
{
|
||||
observer(req);
|
||||
}
|
||||
}
|
||||
auto &filters = ctrlInfo._binders[req->method()]->_filters;
|
||||
if (_postRoutingAdvices.empty())
|
||||
{
|
||||
if (!filters.empty())
|
||||
{
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
|
||||
FiltersFunction::doFilters(filters, req, callbackPtr, needSetJsessionid, sessionIdPtr, [=, &binder]() mutable {
|
||||
doPreHandlingAdvices(binder, ctrlInfo, req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
doPreHandlingAdvices(binder, ctrlInfo, req, std::move(callback), needSetJsessionid, std::move(sessionId));
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
doControllerHandler(binder, ctrlInfo, req, std::move(callback), needSetJsessionid, std::move(sessionId));
|
||||
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
|
||||
doAdvicesChain(_postRoutingAdvices,
|
||||
0,
|
||||
req,
|
||||
callbackPtr,
|
||||
[callbackPtr, &filters, sessionId = std::move(sessionId), req, needSetJsessionid, &ctrlInfo, this, &binder]() mutable {
|
||||
if (!filters.empty())
|
||||
{
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
FiltersFunction::doFilters(filters, req, callbackPtr, needSetJsessionid, sessionIdPtr, [=, &binder]() mutable {
|
||||
doPreHandlingAdvices(binder, ctrlInfo, req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
doPreHandlingAdvices(binder, ctrlInfo, req, std::move(*callbackPtr), needSetJsessionid, std::move(sessionId));
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -234,7 +270,7 @@ void HttpSimpleControllersRouter::init(const std::vector<trantor::EventLoop *> &
|
||||
for (size_t i = 0; i < Invalid; i++)
|
||||
{
|
||||
auto &binder = item._binders[i];
|
||||
if(binder)
|
||||
if (binder)
|
||||
{
|
||||
binder->_filters = FiltersFunction::createFilters(binder->_filterNames);
|
||||
for (auto ioloop : ioLoops)
|
||||
@ -244,4 +280,44 @@ void HttpSimpleControllersRouter::init(const std::vector<trantor::EventLoop *> &
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HttpSimpleControllersRouter::doPreHandlingAdvices(const CtrlBinderPtr &ctrlBinderPtr,
|
||||
const SimpleControllerRouterItem &routerItem,
|
||||
const HttpRequestImplPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId)
|
||||
{
|
||||
if (!_preHandlingObservers.empty())
|
||||
{
|
||||
for (auto &observer : _preHandlingObservers)
|
||||
{
|
||||
observer(req);
|
||||
}
|
||||
}
|
||||
if (_preHandlingAdvices.empty())
|
||||
{
|
||||
doControllerHandler(ctrlBinderPtr, routerItem, req, std::move(callback), needSetJsessionid, std::move(sessionId));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto callbackPtr = std::make_shared<std::function<void(const HttpResponsePtr &)>>(std::move(callback));
|
||||
auto sessionIdPtr = std::make_shared<std::string>(std::move(sessionId));
|
||||
doAdvicesChain(_preHandlingAdvices,
|
||||
0,
|
||||
req,
|
||||
std::make_shared<std::function<void(const HttpResponsePtr &)>>([callbackPtr, needSetJsessionid, sessionIdPtr](const HttpResponsePtr &resp) {
|
||||
if (!needSetJsessionid)
|
||||
(*callbackPtr)(resp);
|
||||
else
|
||||
{
|
||||
resp->addCookie("JSESSIONID", *sessionIdPtr);
|
||||
(*callbackPtr)(resp);
|
||||
}
|
||||
}),
|
||||
[this, ctrlBinderPtr, &routerItem, req, callbackPtr, needSetJsessionid, sessionIdPtr]() {
|
||||
doControllerHandler(ctrlBinderPtr, routerItem, req, std::move(*callbackPtr), needSetJsessionid, std::move(*sessionIdPtr));
|
||||
});
|
||||
}
|
||||
}
|
@ -15,6 +15,7 @@
|
||||
#pragma once
|
||||
#include "HttpRequestImpl.h"
|
||||
#include "HttpResponseImpl.h"
|
||||
#include "HttpControllersRouter.h"
|
||||
#include <drogon/HttpSimpleController.h>
|
||||
#include <trantor/utils/NonCopyable.h>
|
||||
#include <drogon/HttpBinder.h>
|
||||
@ -30,48 +31,82 @@
|
||||
namespace drogon
|
||||
{
|
||||
|
||||
class HttpAppFrameworkImpl;
|
||||
class HttpControllersRouter;
|
||||
class HttpSimpleControllersRouter : public trantor::NonCopyable
|
||||
{
|
||||
public:
|
||||
explicit HttpSimpleControllersRouter(HttpControllersRouter &httpCtrlRouter)
|
||||
: _httpCtrlsRouter(httpCtrlRouter) {}
|
||||
void registerHttpSimpleController(const std::string &pathName,
|
||||
const std::string &ctrlName,
|
||||
const std::vector<any> &filtersAndMethods);
|
||||
void route(const HttpRequestImplPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId);
|
||||
void init(const std::vector<trantor::EventLoop *> &ioLoops);
|
||||
HttpSimpleControllersRouter(HttpControllersRouter &httpCtrlRouter,
|
||||
const std::deque<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>>
|
||||
&postRoutingAdvices,
|
||||
const std::deque<std::function<void(const HttpRequestPtr &)>>
|
||||
&postRoutingObservers,
|
||||
const std::vector<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>>
|
||||
&preHandlingAdvices,
|
||||
const std::vector<std::function<void(const HttpRequestPtr &)>>
|
||||
&preHandlingObservers)
|
||||
: _httpCtrlsRouter(httpCtrlRouter),
|
||||
_postRoutingAdvices(postRoutingAdvices),
|
||||
_preHandlingAdvices(preHandlingAdvices),
|
||||
_postRoutingObservers(postRoutingObservers),
|
||||
_preHandlingObservers(preHandlingObservers)
|
||||
{
|
||||
}
|
||||
|
||||
void registerHttpSimpleController(const std::string &pathName,
|
||||
const std::string &ctrlName,
|
||||
const std::vector<any> &filtersAndMethods);
|
||||
void route(const HttpRequestImplPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId);
|
||||
void init(const std::vector<trantor::EventLoop *> &ioLoops);
|
||||
|
||||
private:
|
||||
HttpControllersRouter &_httpCtrlsRouter;
|
||||
HttpControllersRouter &_httpCtrlsRouter;
|
||||
const std::deque<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>>
|
||||
&_postRoutingAdvices;
|
||||
const std::vector<std::function<void(const HttpRequestPtr &,
|
||||
const AdviceCallback &,
|
||||
const AdviceChainCallback &)>>
|
||||
&_preHandlingAdvices;
|
||||
const std::deque<std::function<void(const HttpRequestPtr &)>>
|
||||
&_postRoutingObservers;
|
||||
const std::vector<std::function<void(const HttpRequestPtr &)>>
|
||||
&_preHandlingObservers;
|
||||
struct CtrlBinder
|
||||
{
|
||||
std::shared_ptr<HttpSimpleControllerBase> _controller;
|
||||
std::vector<std::string> _filterNames;
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> _filters;
|
||||
std::map<trantor::EventLoop *, std::shared_ptr<HttpResponse>> _responsePtrMap;
|
||||
bool _isCORS = false;
|
||||
};
|
||||
typedef std::shared_ptr<CtrlBinder> CtrlBinderPtr;
|
||||
|
||||
struct CtrlBinder
|
||||
{
|
||||
std::shared_ptr<HttpSimpleControllerBase> _controller;
|
||||
std::vector<std::string> _filterNames;
|
||||
std::vector<std::shared_ptr<HttpFilterBase>> _filters;
|
||||
std::map<trantor::EventLoop *, std::shared_ptr<HttpResponse>> _responsePtrMap;
|
||||
bool _isCORS = false;
|
||||
};
|
||||
typedef std::shared_ptr<CtrlBinder> CtrlBinderPtr;
|
||||
struct SimpleControllerRouterItem
|
||||
{
|
||||
std::string _controllerName;
|
||||
CtrlBinderPtr _binders[Invalid] = {nullptr};
|
||||
};
|
||||
std::unordered_map<std::string, SimpleControllerRouterItem> _simpCtrlMap;
|
||||
std::mutex _simpCtrlMutex;
|
||||
|
||||
struct SimpleControllerRouterItem
|
||||
{
|
||||
std::string _controllerName;
|
||||
CtrlBinderPtr _binders[Invalid] = {nullptr};
|
||||
};
|
||||
std::unordered_map<std::string, SimpleControllerRouterItem> _simpCtrlMap;
|
||||
std::mutex _simpCtrlMutex;
|
||||
|
||||
void doControllerHandler(const CtrlBinderPtr &ctrlBinderPtr,
|
||||
const SimpleControllerRouterItem &routerItem,
|
||||
const HttpRequestImplPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId);
|
||||
void doPreHandlingAdvices(const CtrlBinderPtr &ctrlBinderPtr,
|
||||
const SimpleControllerRouterItem &routerItem,
|
||||
const HttpRequestImplPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId);
|
||||
void doControllerHandler(const CtrlBinderPtr &ctrlBinderPtr,
|
||||
const SimpleControllerRouterItem &routerItem,
|
||||
const HttpRequestImplPtr &req,
|
||||
std::function<void(const HttpResponsePtr &)> &&callback,
|
||||
bool needSetJsessionid,
|
||||
std::string &&sessionId);
|
||||
};
|
||||
} // namespace drogon
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <drogon/WebSocketConnection.h>
|
||||
#include <drogon/WebSocketController.h>
|
||||
#include <trantor/utils/NonCopyable.h>
|
||||
|
||||
namespace drogon
|
||||
{
|
||||
@ -25,7 +26,7 @@ typedef std::shared_ptr<WebSocketConnectionImpl> WebSocketConnectionImplPtr;
|
||||
|
||||
class WebSocketMessageParser
|
||||
{
|
||||
public:
|
||||
public:
|
||||
bool parse(trantor::MsgBuffer *buffer);
|
||||
bool gotAll(std::string &message, WebSocketMessageType &type)
|
||||
{
|
||||
@ -37,15 +38,17 @@ class WebSocketMessageParser
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
std::string _message;
|
||||
WebSocketMessageType _type;
|
||||
bool _gotAll = false;
|
||||
};
|
||||
|
||||
class WebSocketConnectionImpl : public WebSocketConnection, public std::enable_shared_from_this<WebSocketConnectionImpl>
|
||||
class WebSocketConnectionImpl : public WebSocketConnection,
|
||||
public std::enable_shared_from_this<WebSocketConnectionImpl>,
|
||||
public trantor::NonCopyable
|
||||
{
|
||||
public:
|
||||
public:
|
||||
explicit WebSocketConnectionImpl(const trantor::TcpConnectionPtr &conn, bool isServer = true);
|
||||
|
||||
virtual void send(const char *msg, uint64_t len, const WebSocketMessageType &type = WebSocketMessageType::Text) override;
|
||||
@ -128,7 +131,7 @@ class WebSocketConnectionImpl : public WebSocketConnection, public std::enable_s
|
||||
_closeCallback(shared_from_this());
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
trantor::TcpConnectionPtr _tcpConn;
|
||||
trantor::InetAddress _localAddr;
|
||||
trantor::InetAddress _peerAddr;
|
||||
|
Loading…
x
Reference in New Issue
Block a user