Modify AOP

This commit is contained in:
an-tao 2019-04-18 23:18:13 +08:00
parent a9c4205d92
commit f6411812d5
7 changed files with 127 additions and 130 deletions

View File

@ -203,7 +203,7 @@ class HttpAppFramework : public trantor::NonCopyable
*/
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.
///The @param advice is called immediately after the request is handled and a response object is created by handlers.
virtual void registerPostHandlingAdvice(const std::function<void(const HttpRequestPtr &, const HttpResponsePtr &)> &advice) = 0;
///End of AOP methods

View File

@ -738,66 +738,29 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestImplPtr &req, std::fu
observer(req);
}
}
if (_postHandlingAdvices.empty())
if (_preRoutingAdvices.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));
});
}
_httpSimpleCtrlsRouter.route(req, std::move(callback), needSetJsessionid, std::move(sessionId));
}
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));
});
}
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));
});
}
}

View File

@ -47,10 +47,10 @@ struct InitBeforeMainFunction
};
class HttpAppFrameworkImpl : public HttpAppFramework
{
public:
public:
HttpAppFrameworkImpl()
: _httpCtrlsRouter(_postRoutingAdvices, _postRoutingObservers, _preHandlingAdvices, _preHandlingObservers),
_httpSimpleCtrlsRouter(_httpCtrlsRouter, _postRoutingAdvices, _postRoutingObservers, _preHandlingAdvices, _preHandlingObservers),
: _httpCtrlsRouter(_postRoutingAdvices, _postRoutingObservers, _preHandlingAdvices, _preHandlingObservers, _postHandlingAdvices),
_httpSimpleCtrlsRouter(_httpCtrlsRouter, _postRoutingAdvices, _postRoutingObservers, _preHandlingAdvices, _preHandlingObservers, _postHandlingAdvices),
_uploadPath(_rootPath + "uploads"),
_connectionNum(0)
{
@ -227,7 +227,7 @@ public:
}
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>(),

View File

@ -267,33 +267,6 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
bool needSetJsessionid,
std::string &&sessionId)
{
if (req->method() == Options)
{
auto resp = HttpResponse::newHttpResponse();
resp->setContentTypeCode(ContentType::CT_TEXT_PLAIN);
std::string methods = "OPTIONS,";
if (routerItem._binders[Get] && routerItem._binders[Get]->_isCORS)
{
methods.append("GET,HEAD,");
}
if (routerItem._binders[Post] && routerItem._binders[Post]->_isCORS)
{
methods.append("POST,");
}
if (routerItem._binders[Put] && routerItem._binders[Put]->_isCORS)
{
methods.append("PUT,");
}
if (routerItem._binders[Delete] && routerItem._binders[Delete]->_isCORS)
{
methods.append("DELETE,");
}
methods.resize(methods.length() - 1);
resp->addHeader("ALLOW", methods);
callback(resp);
return;
}
HttpResponsePtr &responsePtr = ctrlBinderPtr->_responsePtrMap[req->getLoop()];
if (responsePtr && (responsePtr->expiredTime() == 0 || (trantor::Date::now() < responsePtr->creationDate().after(responsePtr->expiredTime()))))
{
@ -301,14 +274,14 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
LOG_TRACE << "Use cached response";
if (!needSetJsessionid)
callback(responsePtr);
invokeCallback(callback, req, responsePtr);
else
{
//make a copy response;
auto newResp = std::make_shared<HttpResponseImpl>(*std::dynamic_pointer_cast<HttpResponseImpl>(responsePtr));
newResp->setExpiredTime(-1); //make it temporary
newResp->addCookie("JSESSIONID", sessionId);
callback(newResp);
invokeCallback(callback, req, newResp);
}
return;
}
@ -376,7 +349,7 @@ void HttpControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlBinderP
}
newResp->addCookie("JSESSIONID", sessionId);
}
callback(newResp);
invokeCallback(callback, req, newResp);
});
return;
}
@ -388,6 +361,32 @@ void HttpControllersRouter::doPreHandlingAdvices(const CtrlBinderPtr &ctrlBinder
bool needSetJsessionid,
std::string &&sessionId)
{
if (req->method() == Options)
{
auto resp = HttpResponse::newHttpResponse();
resp->setContentTypeCode(ContentType::CT_TEXT_PLAIN);
std::string methods = "OPTIONS,";
if (routerItem._binders[Get] && routerItem._binders[Get]->_isCORS)
{
methods.append("GET,HEAD,");
}
if (routerItem._binders[Post] && routerItem._binders[Post]->_isCORS)
{
methods.append("POST,");
}
if (routerItem._binders[Put] && routerItem._binders[Put]->_isCORS)
{
methods.append("PUT,");
}
if (routerItem._binders[Delete] && routerItem._binders[Delete]->_isCORS)
{
methods.append("DELETE,");
}
methods.resize(methods.length() - 1);
resp->addHeader("ALLOW", methods);
callback(resp);
return;
}
if (!_preHandlingObservers.empty())
{
for (auto &observer : _preHandlingObservers)

View File

@ -30,7 +30,7 @@ namespace drogon
{
class HttpControllersRouter : public trantor::NonCopyable
{
public:
public:
HttpControllersRouter(const std::deque<std::function<void(const HttpRequestPtr &,
const AdviceCallback &,
const AdviceChainCallback &)>>
@ -42,11 +42,15 @@ public:
const AdviceChainCallback &)>>
&preHandlingAdvices,
const std::vector<std::function<void(const HttpRequestPtr &)>>
&preHandlingObservers)
&preHandlingObservers,
const std::deque<std::function<void(const HttpRequestPtr &,
const HttpResponsePtr &)>>
&postHandlingAdvices)
: _postRoutingAdvices(postRoutingAdvices),
_preHandlingAdvices(preHandlingAdvices),
_postRoutingObservers(postRoutingObservers),
_preHandlingObservers(preHandlingObservers)
_preHandlingObservers(preHandlingObservers),
_postHandlingAdvices(postHandlingAdvices)
{
}
void init(const std::vector<trantor::EventLoop *> &ioLoops);
@ -59,7 +63,7 @@ public:
bool needSetJsessionid,
std::string &&sessionId);
private:
private:
struct CtrlBinder
{
internal::HttpBinderBasePtr _binderPtr;
@ -92,6 +96,10 @@ private:
&_postRoutingObservers;
const std::vector<std::function<void(const HttpRequestPtr &)>>
&_preHandlingObservers;
const std::deque<std::function<void(const HttpRequestPtr &,
const HttpResponsePtr &)>>
&_postHandlingAdvices;
void doPreHandlingAdvices(const CtrlBinderPtr &ctrlBinderPtr,
const HttpControllerRouterItem &routerItem,
const HttpRequestImplPtr &req,
@ -105,5 +113,15 @@ private:
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&sessionId);
void invokeCallback(const std::function<void(const HttpResponsePtr &)> &callback,
const HttpRequestImplPtr &req,
const HttpResponsePtr &resp)
{
for (auto &advice : _postHandlingAdvices)
{
advice(req, resp);
}
callback(resp);
}
};
} // namespace drogon

View File

@ -171,46 +171,20 @@ void HttpSimpleControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlB
auto &controller = ctrlBinderPtr->_controller;
if (controller)
{
if (req->method() == Options)
{
auto resp = HttpResponse::newHttpResponse();
resp->setContentTypeCode(ContentType::CT_TEXT_PLAIN);
std::string methods = "OPTIONS,";
if (routerItem._binders[Get] && routerItem._binders[Get]->_isCORS)
{
methods.append("GET,HEAD,");
}
if (routerItem._binders[Post] && routerItem._binders[Post]->_isCORS)
{
methods.append("POST,");
}
if (routerItem._binders[Put] && routerItem._binders[Put]->_isCORS)
{
methods.append("PUT,");
}
if (routerItem._binders[Delete] && routerItem._binders[Delete]->_isCORS)
{
methods.append("DELETE,");
}
methods.resize(methods.length() - 1);
resp->addHeader("ALLOW", methods);
callback(resp);
return;
}
HttpResponsePtr &responsePtr = ctrlBinderPtr->_responsePtrMap[req->getLoop()];
if (responsePtr && (responsePtr->expiredTime() == 0 || (trantor::Date::now() < responsePtr->creationDate().after(responsePtr->expiredTime()))))
{
//use cached response!
LOG_TRACE << "Use cached response";
if (!needSetJsessionid)
callback(responsePtr);
invokeCallback(callback, req, responsePtr);
else
{
//make a copy response;
auto newResp = std::make_shared<HttpResponseImpl>(*std::dynamic_pointer_cast<HttpResponseImpl>(responsePtr));
newResp->setExpiredTime(-1); //make it temporary
newResp->addCookie("JSESSIONID", sessionId);
callback(newResp);
invokeCallback(callback, req, newResp);
}
return;
}
@ -244,7 +218,7 @@ void HttpSimpleControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlB
}
newResp->addCookie("JSESSIONID", sessionId);
}
callback(newResp);
invokeCallback(callback, req, newResp);
});
}
@ -257,8 +231,7 @@ void HttpSimpleControllersRouter::doControllerHandler(const CtrlBinderPtr &ctrlB
auto res = drogon::HttpResponse::newNotFoundResponse();
if (needSetJsessionid)
res->addCookie("JSESSIONID", sessionId);
callback(res);
invokeCallback(callback, req, res);
}
}
@ -289,6 +262,32 @@ void HttpSimpleControllersRouter::doPreHandlingAdvices(const CtrlBinderPtr &ctrl
bool needSetJsessionid,
std::string &&sessionId)
{
if (req->method() == Options)
{
auto resp = HttpResponse::newHttpResponse();
resp->setContentTypeCode(ContentType::CT_TEXT_PLAIN);
std::string methods = "OPTIONS,";
if (routerItem._binders[Get] && routerItem._binders[Get]->_isCORS)
{
methods.append("GET,HEAD,");
}
if (routerItem._binders[Post] && routerItem._binders[Post]->_isCORS)
{
methods.append("POST,");
}
if (routerItem._binders[Put] && routerItem._binders[Put]->_isCORS)
{
methods.append("PUT,");
}
if (routerItem._binders[Delete] && routerItem._binders[Delete]->_isCORS)
{
methods.append("DELETE,");
}
methods.resize(methods.length() - 1);
resp->addHeader("ALLOW", methods);
callback(resp);
return;
}
if (!_preHandlingObservers.empty())
{
for (auto &observer : _preHandlingObservers)

View File

@ -33,7 +33,7 @@ namespace drogon
class HttpSimpleControllersRouter : public trantor::NonCopyable
{
public:
public:
HttpSimpleControllersRouter(HttpControllersRouter &httpCtrlRouter,
const std::deque<std::function<void(const HttpRequestPtr &,
const AdviceCallback &,
@ -46,12 +46,16 @@ public:
const AdviceChainCallback &)>>
&preHandlingAdvices,
const std::vector<std::function<void(const HttpRequestPtr &)>>
&preHandlingObservers)
&preHandlingObservers,
const std::deque<std::function<void(const HttpRequestPtr &,
const HttpResponsePtr &)>>
&postHandlingAdvices)
: _httpCtrlsRouter(httpCtrlRouter),
_postRoutingAdvices(postRoutingAdvices),
_preHandlingAdvices(preHandlingAdvices),
_postRoutingObservers(postRoutingObservers),
_preHandlingObservers(preHandlingObservers)
_preHandlingObservers(preHandlingObservers),
_postHandlingAdvices(postHandlingAdvices)
{
}
@ -64,7 +68,7 @@ public:
std::string &&sessionId);
void init(const std::vector<trantor::EventLoop *> &ioLoops);
private:
private:
HttpControllersRouter &_httpCtrlsRouter;
const std::deque<std::function<void(const HttpRequestPtr &,
const AdviceCallback &,
@ -78,6 +82,10 @@ private:
&_postRoutingObservers;
const std::vector<std::function<void(const HttpRequestPtr &)>>
&_preHandlingObservers;
const std::deque<std::function<void(const HttpRequestPtr &,
const HttpResponsePtr &)>>
&_postHandlingAdvices;
struct CtrlBinder
{
std::shared_ptr<HttpSimpleControllerBase> _controller;
@ -108,5 +116,15 @@ private:
std::function<void(const HttpResponsePtr &)> &&callback,
bool needSetJsessionid,
std::string &&sessionId);
void invokeCallback(const std::function<void(const HttpResponsePtr &)> &callback,
const HttpRequestImplPtr &req,
const HttpResponsePtr &resp)
{
for (auto &advice : _postHandlingAdvices)
{
advice(req,resp);
}
callback(resp);
}
};
} // namespace drogon