From 99ba19ebca54a9db685acf4ddbf032ec2cec5203 Mon Sep 17 00:00:00 2001 From: antao Date: Thu, 2 Aug 2018 15:38:06 +0800 Subject: [PATCH] change doFilter interface --- drogon_ctl/create_controller.cc | 8 +- examples/simple_example/JsonTestController.cc | 2 +- examples/simple_example/JsonTestController.h | 2 +- examples/simple_example/ListParaCtl.cc | 4 +- examples/simple_example/ListParaCtl.h | 2 +- examples/simple_example/TestController.cc | 2 +- examples/simple_example/TestController.h | 2 +- examples/simple_example/TestViewCtl.cc | 2 +- examples/simple_example/TestViewCtl.h | 2 +- examples/simple_example/TimeFilter.cpp | 20 +- examples/simple_example/TimeFilter.h | 4 +- examples/simple_example/api_v1_ApiTest.cc | 4 +- examples/simple_example/api_v1_ApiTest.h | 4 +- examples/simple_example/main.cc | 12 +- lib/inc/drogon/DeleteFilter.h | 4 +- lib/inc/drogon/GetFilter.h | 4 +- lib/inc/drogon/HttpApiBinder.h | 12 +- lib/inc/drogon/HttpFilter.h | 6 +- lib/inc/drogon/HttpSimpleController.h | 2 +- lib/inc/drogon/PostFilter.h | 4 +- lib/inc/drogon/PutFilter.h | 4 +- lib/inc/drogon/utils/FunctionTraits.h | 7 +- lib/src/DeleteFilter.cc | 13 +- lib/src/GetFilter.cc | 13 +- lib/src/HttpAppFramework.cc | 207 ++++++++++-------- lib/src/HttpContext.cc | 54 +++-- lib/src/HttpContext.h | 18 +- lib/src/HttpRequestImpl.h | 1 + lib/src/HttpServer.cc | 16 +- lib/src/HttpServer.h | 5 +- lib/src/PostFilter.cc | 11 +- lib/src/PutFilter.cc | 12 +- 32 files changed, 258 insertions(+), 205 deletions(-) diff --git a/drogon_ctl/create_controller.cc b/drogon_ctl/create_controller.cc index f60298f3..9b2726f8 100755 --- a/drogon_ctl/create_controller.cc +++ b/drogon_ctl/create_controller.cc @@ -132,7 +132,7 @@ void create_controller::newSimpleControllerHeaderFile(std::ofstream &file,const file< & callback)override;\n"; + file< & callback)override;\n"; file< & callback)\n"; + file<<"void "< & callback)\n"; file<<"{\n"; file<<" //write your application logic here\n"; file<<"}"; @@ -215,9 +215,9 @@ void create_controller::newApiControllerHeaderFile(std::ofstream &file,const std file<&callback,int p1,std::string p2);\n"; - file<&callback,double p1,int p2) const;\n"; indent.resize(indent.length()-4); file< -void JsonTestController::asyncHandleHttpRequest(const HttpRequest& req,const std::function&callback) +void JsonTestController::asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function&callback) { Json::Value json; json["path"]="json"; diff --git a/examples/simple_example/JsonTestController.h b/examples/simple_example/JsonTestController.h index 404848ea..af61352a 100755 --- a/examples/simple_example/JsonTestController.h +++ b/examples/simple_example/JsonTestController.h @@ -7,7 +7,7 @@ class JsonTestController:public drogon::HttpSimpleController { public: //TestController(){} - virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function&callback)override; + virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function&callback)override; PATH_LIST_BEGIN PATH_ADD("/json"); diff --git a/examples/simple_example/ListParaCtl.cc b/examples/simple_example/ListParaCtl.cc index ed78614f..1a64ee54 100755 --- a/examples/simple_example/ListParaCtl.cc +++ b/examples/simple_example/ListParaCtl.cc @@ -1,10 +1,10 @@ #include "ListParaCtl.h" -void ListParaCtl::asyncHandleHttpRequest(const HttpRequest& req,const std::function&callback) +void ListParaCtl::asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function&callback) { //write your application logic here HttpViewData data; data.insert("title",std::string("list parameters")); - data.insert("parameters",req.getParameters()); + data.insert("parameters",req->getParameters()); auto res=drogon::HttpResponse::newHttpViewResponse("ListParaView.csp",data); callback(*res); } \ No newline at end of file diff --git a/examples/simple_example/ListParaCtl.h b/examples/simple_example/ListParaCtl.h index 6745f42f..2a4452a9 100755 --- a/examples/simple_example/ListParaCtl.h +++ b/examples/simple_example/ListParaCtl.h @@ -4,7 +4,7 @@ using namespace drogon; class ListParaCtl:public drogon::HttpSimpleController { public: - virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function &callback)override; + virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function &callback)override; PATH_LIST_BEGIN //list path definations here; //PATH_ADD("/path","filter1","filter2",...); diff --git a/examples/simple_example/TestController.cc b/examples/simple_example/TestController.cc index f9c4d8f9..6fed9d57 100755 --- a/examples/simple_example/TestController.cc +++ b/examples/simple_example/TestController.cc @@ -1,6 +1,6 @@ #include "TestController.h" using namespace example; -void TestController::asyncHandleHttpRequest(const HttpRequest& req,const std::function&callback) +void TestController::asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function&callback) { //write your application logic here auto resp=HttpResponse::newHttpResponse(); diff --git a/examples/simple_example/TestController.h b/examples/simple_example/TestController.h index d5234a9e..91f80a26 100755 --- a/examples/simple_example/TestController.h +++ b/examples/simple_example/TestController.h @@ -5,7 +5,7 @@ namespace example{ class TestController:public drogon::HttpSimpleController { public: - virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function&callback)override; + virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function&callback)override; PATH_LIST_BEGIN //list path definations here; //PATH_ADD("/path","filter1","filter2",...); diff --git a/examples/simple_example/TestViewCtl.cc b/examples/simple_example/TestViewCtl.cc index a39d0b93..3f55c690 100755 --- a/examples/simple_example/TestViewCtl.cc +++ b/examples/simple_example/TestViewCtl.cc @@ -1,5 +1,5 @@ #include "TestViewCtl.h" -void TestViewCtl::asyncHandleHttpRequest(const HttpRequest& req,const std::function&callback) +void TestViewCtl::asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function&callback) { //write your application logic here drogon::HttpViewData data; diff --git a/examples/simple_example/TestViewCtl.h b/examples/simple_example/TestViewCtl.h index c0a803ad..181516ad 100755 --- a/examples/simple_example/TestViewCtl.h +++ b/examples/simple_example/TestViewCtl.h @@ -4,7 +4,7 @@ using namespace drogon; class TestViewCtl:public drogon::HttpSimpleController { public: - virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function&callback)override; + virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function&callback)override; PATH_LIST_BEGIN //list path definations here; //PATH_ADD("/path","filter1","filter2",...); diff --git a/examples/simple_example/TimeFilter.cpp b/examples/simple_example/TimeFilter.cpp index 82e48fa2..9f0ac345 100755 --- a/examples/simple_example/TimeFilter.cpp +++ b/examples/simple_example/TimeFilter.cpp @@ -6,29 +6,33 @@ #include #include #define VDate "visitDate" -std::shared_ptr TimeFilter::doFilter(const HttpRequest& req) +void TimeFilter::doFilter(const HttpRequestPtr& req, + const FilterCallback &cb, + const FilterChainCallback &ccb) { trantor::Date now=trantor::Date::date(); LOG_TRACE<<""; - if(req.session()->find(VDate)) + if(req->session()->find(VDate)) { - auto lastDate=req.session()->get(VDate); + auto lastDate=req->session()->get(VDate); LOG_TRACE<<"last:"<insert(VDate,now); + req->session()->insert(VDate,now); LOG_TRACE<<"update visitDate"; if(now>lastDate.after(10)) { //10 sec later can visit again; - return nullptr; + ccb(); + return; } else { auto res=std::shared_ptr(drogon::HttpResponse::newHttpResponse()); res->setBody("Visit interval should be at least 10 seconds"); - return res; + cb(res); + return; } } LOG_TRACE<<"first visit,insert visitDate"; - req.session()->insert(VDate,now); - return nullptr; + req->session()->insert(VDate,now); + ccb(); } \ No newline at end of file diff --git a/examples/simple_example/TimeFilter.h b/examples/simple_example/TimeFilter.h index 747671b3..0cd32dff 100755 --- a/examples/simple_example/TimeFilter.h +++ b/examples/simple_example/TimeFilter.h @@ -9,7 +9,9 @@ using namespace drogon; class TimeFilter: public drogon::HttpFilter { public: - virtual std::shared_ptr doFilter(const HttpRequest& req) override; + virtual void doFilter(const HttpRequestPtr& req, + const FilterCallback &cb, + const FilterChainCallback &ccb) override; }; diff --git a/examples/simple_example/api_v1_ApiTest.cc b/examples/simple_example/api_v1_ApiTest.cc index 58e1d264..9114a39a 100755 --- a/examples/simple_example/api_v1_ApiTest.cc +++ b/examples/simple_example/api_v1_ApiTest.cc @@ -1,7 +1,7 @@ #include "api_v1_ApiTest.h" using namespace api::v1; //add definition of your processing function here -void ApiTest::get(const HttpRequest& req,const std::function&callback,int p1,std::string p2) +void ApiTest::get(const HttpRequestPtr& req,const std::function&callback,int p1,std::string p2) { HttpViewData data; data.insert("title",std::string("ApiTest::get")); @@ -12,7 +12,7 @@ void ApiTest::get(const HttpRequest& req,const std::function&callback,double p1,int p2) const +void ApiTest::your_method_name(const HttpRequestPtr& req,const std::function&callback,double p1,int p2) const { HttpViewData data; data.insert("title",std::string("ApiTest::get")); diff --git a/examples/simple_example/api_v1_ApiTest.h b/examples/simple_example/api_v1_ApiTest.h index b5859fc5..f7b5ef28 100755 --- a/examples/simple_example/api_v1_ApiTest.h +++ b/examples/simple_example/api_v1_ApiTest.h @@ -14,8 +14,8 @@ namespace api METHOD_LIST_END //your declaration of processing function maybe like this: - void get(const HttpRequest& req,const std::function&callback,int p1,std::string p2); - void your_method_name(const HttpRequest& req,const std::function&callback,double p1,int p2) const; + void get(const HttpRequestPtr& req,const std::function&callback,int p1,std::string p2); + void your_method_name(const HttpRequestPtr& req,const std::function&callback,double p1,int p2) const; }; } } diff --git a/examples/simple_example/main.cc b/examples/simple_example/main.cc index 646530e3..85259849 100755 --- a/examples/simple_example/main.cc +++ b/examples/simple_example/main.cc @@ -9,7 +9,7 @@ using namespace drogon; class A { public: - void handle(const HttpRequest& req, + void handle(const HttpRequestPtr& req, const std::function&callback, int p1,const std::string &p2,const std::string &p3,int p4) const { @@ -29,7 +29,7 @@ public: class B { public: - void operator ()(const HttpRequest& req,const std::function&callback,int p1,int p2) + void operator ()(const HttpRequestPtr& req,const std::function&callback,int p1,int p2) { HttpViewData data; data.insert("title",std::string("ApiTest::get")); @@ -51,7 +51,7 @@ namespace api METHOD_ADD(Test::get,"/{2}/{1}",1,"drogon::GetFilter");//path will be /api/v1/test/get/{arg2}/{arg1} METHOD_ADD(Test::list,"/{2}/info",0,"drogon::GetFilter");//path will be /api/v1/test/{arg2}/info METHOD_LIST_END - void get(const HttpRequest& req,const std::function&callback,int p1,int p2) const + void get(const HttpRequestPtr& req,const std::function&callback,int p1,int p2) const { HttpViewData data; data.insert("title",std::string("ApiTest::get")); @@ -62,7 +62,7 @@ namespace api auto res=HttpResponse::newHttpViewResponse("ListParaView",data); callback(*res); } - void list(const HttpRequest& req,const std::function&callback,int p1,int p2) const + void list(const HttpRequestPtr& req,const std::function&callback,int p1,int p2) const { HttpViewData data; data.insert("title",std::string("ApiTest::get")); @@ -95,7 +95,7 @@ int main() //class function drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle1/{1}/{2}/?p3={3}&p4={4}",&A::handle); //lambda example - drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle2/{1}/{2}",[](const HttpRequest&req,const std::function&callback,int a,float b){ + drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle2/{1}/{2}",[](const HttpRequestPtr&req,const std::function&callback,int a,float b){ LOG_DEBUG<<"int a="<&,int,const std::string &,const std::string &,int)> + std::function&,int,const std::string &,const std::string &,int)> func=std::bind(&A::handle,&tmp,_1,_2,_3,_4,_5,_6); //api example for std::function drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle4/{4}/{3}/{1}",func); diff --git a/lib/inc/drogon/DeleteFilter.h b/lib/inc/drogon/DeleteFilter.h index 7a06fcf3..e34a7a36 100755 --- a/lib/inc/drogon/DeleteFilter.h +++ b/lib/inc/drogon/DeleteFilter.h @@ -22,6 +22,8 @@ namespace drogon { public: DeleteFilter(){} - virtual std::shared_ptr doFilter(const HttpRequest& req) override ; + virtual void doFilter(const HttpRequestPtr& req, + const FilterCallback &fcb, + const FilterChainCallback &fccb) override ; }; } \ No newline at end of file diff --git a/lib/inc/drogon/GetFilter.h b/lib/inc/drogon/GetFilter.h index ec74f04e..c3198901 100755 --- a/lib/inc/drogon/GetFilter.h +++ b/lib/inc/drogon/GetFilter.h @@ -22,6 +22,8 @@ namespace drogon { public: GetFilter(){} - virtual std::shared_ptr doFilter(const HttpRequest& req) override ; + virtual void doFilter(const HttpRequestPtr& req, + const FilterCallback &fcb, + const FilterChainCallback &fccb) override ; }; } \ No newline at end of file diff --git a/lib/inc/drogon/HttpApiBinder.h b/lib/inc/drogon/HttpApiBinder.h index 1fb4fe57..7a6ffa7b 100755 --- a/lib/inc/drogon/HttpApiBinder.h +++ b/lib/inc/drogon/HttpApiBinder.h @@ -48,7 +48,7 @@ namespace drogon{ { public: virtual void handleHttpApiRequest(std::list &pathParameter, - const HttpRequest& req,std::functioncallback) + const HttpRequestPtr& req,std::functioncallback) =0; virtual size_t paramCount()=0; virtual ~HttpApiBinderBase(){} @@ -60,7 +60,7 @@ namespace drogon{ public: typedef FUNCTION FunctionType; virtual void handleHttpApiRequest(std::list &pathParameter, - const HttpRequest& req,std::functioncallback) override + const HttpRequestPtr& req,std::functioncallback) override { run(pathParameter,req,callback); } @@ -95,7 +95,7 @@ namespace drogon{ > typename std::enable_if<(sizeof...(Values) < Boundary), void>::type run( std::list &pathParameter, - const HttpRequest& req,std::functioncallback, + const HttpRequestPtr& req,std::functioncallback, Values&&... values ) { @@ -124,7 +124,7 @@ namespace drogon{ > typename std::enable_if<(sizeof...(Values) == Boundary), void>::type run( std::list &pathParameter, - const HttpRequest& req,std::functioncallback, + const HttpRequestPtr& req,std::functioncallback, Values&&... values ) { @@ -133,7 +133,7 @@ namespace drogon{ template typename std::enable_if::type callFunction( - const HttpRequest& req,std::functioncallback, + const HttpRequestPtr& req,std::functioncallback, Values&&... values) { static typename traits::class_type obj; @@ -142,7 +142,7 @@ namespace drogon{ template typename std::enable_if::type callFunction( - const HttpRequest& req,std::functioncallback, + const HttpRequestPtr& req,std::functioncallback, Values&&... values) { _func(req,callback,std::move(values)...); diff --git a/lib/inc/drogon/HttpFilter.h b/lib/inc/drogon/HttpFilter.h index 6b1748a1..2d7eb6ca 100755 --- a/lib/inc/drogon/HttpFilter.h +++ b/lib/inc/drogon/HttpFilter.h @@ -21,10 +21,14 @@ namespace drogon { + typedef std::functionFilterCallback; + typedef std::functionFilterChainCallback; class HttpFilterBase:public virtual DrObjectBase { public: - virtual std::shared_ptr doFilter(const HttpRequest& req)=0; + virtual void doFilter(const HttpRequestPtr& req, + const FilterCallback &fcb, + const FilterChainCallback &fccb)=0; virtual ~HttpFilterBase(){} }; template diff --git a/lib/inc/drogon/HttpSimpleController.h b/lib/inc/drogon/HttpSimpleController.h index 830fc41d..a0a86704 100755 --- a/lib/inc/drogon/HttpSimpleController.h +++ b/lib/inc/drogon/HttpSimpleController.h @@ -36,7 +36,7 @@ namespace drogon class HttpSimpleControllerBase:public virtual DrObjectBase { public: - virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function &callback)=0; + virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function &callback)=0; virtual ~HttpSimpleControllerBase(){} }; diff --git a/lib/inc/drogon/PostFilter.h b/lib/inc/drogon/PostFilter.h index 733f2ce9..ebd31123 100755 --- a/lib/inc/drogon/PostFilter.h +++ b/lib/inc/drogon/PostFilter.h @@ -22,6 +22,8 @@ namespace drogon { public: PostFilter(){} - virtual std::shared_ptr doFilter(const HttpRequest& req) override ; + virtual void doFilter(const HttpRequestPtr& req, + const FilterCallback &fcb, + const FilterChainCallback &fccb) override ; }; } \ No newline at end of file diff --git a/lib/inc/drogon/PutFilter.h b/lib/inc/drogon/PutFilter.h index 22aa57dc..1e0aacb8 100755 --- a/lib/inc/drogon/PutFilter.h +++ b/lib/inc/drogon/PutFilter.h @@ -22,6 +22,8 @@ namespace drogon { public: PutFilter(){} - virtual std::shared_ptr doFilter(const HttpRequest& req) override ; + virtual void doFilter(const HttpRequestPtr& req, + const FilterCallback &fcb, + const FilterChainCallback &fccb) override ; }; } \ No newline at end of file diff --git a/lib/inc/drogon/utils/FunctionTraits.h b/lib/inc/drogon/utils/FunctionTraits.h index 1321b731..3eefb0cd 100755 --- a/lib/inc/drogon/utils/FunctionTraits.h +++ b/lib/inc/drogon/utils/FunctionTraits.h @@ -5,6 +5,7 @@ namespace drogon{ class HttpRequest; class HttpResponse; + typedef std::shared_ptr HttpRequestPtr; namespace utility { template struct FunctionTraits; @@ -54,7 +55,7 @@ namespace drogon{ typename... Arguments > struct FunctionTraits< - ReturnType(ClassType::*)(const HttpRequest& req,const std::function&callback,Arguments...) const + ReturnType(ClassType::*)(const HttpRequestPtr& req,const std::function&callback,Arguments...) const > : FunctionTraits { static const bool isHTTPApiFunction=true; static const std::string name(){return std::string("Class Const Api Function");} @@ -66,7 +67,7 @@ namespace drogon{ typename... Arguments > struct FunctionTraits< - ReturnType(ClassType::*)(const HttpRequest& req,const std::function&callback,Arguments...) + ReturnType(ClassType::*)(const HttpRequestPtr& req,const std::function&callback,Arguments...) > : FunctionTraits { static const bool isHTTPApiFunction=true; static const std::string name(){return std::string("Class Api Function");} @@ -77,7 +78,7 @@ namespace drogon{ typename... Arguments > struct FunctionTraits< - ReturnType(*)(const HttpRequest& req,const std::function&callback,Arguments...) + ReturnType(*)(const HttpRequestPtr& req,const std::function&callback,Arguments...) > : FunctionTraits { static const bool isHTTPApiFunction=true; diff --git a/lib/src/DeleteFilter.cc b/lib/src/DeleteFilter.cc index d16591fa..e1f52350 100755 --- a/lib/src/DeleteFilter.cc +++ b/lib/src/DeleteFilter.cc @@ -15,14 +15,15 @@ #include #include "HttpResponseImpl.h" using namespace drogon; -std::shared_ptr DeleteFilter::doFilter(const HttpRequest& req) +void DeleteFilter::doFilter(const HttpRequestPtr& req, + const FilterCallback &fcb, + const FilterChainCallback &fccb) { - if(req.method()==HttpRequest::kDelete) + if(req->method()==HttpRequest::kDelete) { - return nullptr; + fccb(); + return; } auto res=drogon::HttpResponse::notFoundResponse(); - - - return res; + fcb(res); } \ No newline at end of file diff --git a/lib/src/GetFilter.cc b/lib/src/GetFilter.cc index 68476de0..9deff601 100755 --- a/lib/src/GetFilter.cc +++ b/lib/src/GetFilter.cc @@ -15,14 +15,15 @@ #include #include "HttpResponseImpl.h" using namespace drogon; -std::shared_ptr GetFilter::doFilter(const HttpRequest& req) +void GetFilter::doFilter(const HttpRequestPtr& req, + const FilterCallback &fcb, + const FilterChainCallback &fccb) { - if(req.method()==HttpRequest::kGet) + if(req->method()==HttpRequest::kGet) { - return nullptr; + fccb(); + return; } auto res=drogon::HttpResponse::notFoundResponse(); - - - return res; + fcb(res); } \ No newline at end of file diff --git a/lib/src/HttpAppFramework.cc b/lib/src/HttpAppFramework.cc index b9b5728b..bfc72c68 100755 --- a/lib/src/HttpAppFramework.cc +++ b/lib/src/HttpAppFramework.cc @@ -64,8 +64,8 @@ namespace drogon virtual trantor::EventLoop *loop() override; private: std::vector> _listeners; - void onAsyncRequest(const HttpRequest& req,const std::function & callback); - void readSendFile(const std::string& filePath,const HttpRequest& req, HttpResponse* resp); + void onAsyncRequest(const HttpRequestPtr& req,const std::function & callback); + void readSendFile(const std::string& filePath,const HttpRequestPtr& req, HttpResponse* resp); void addApiPath(const std::string &path, const HttpApiBinderBasePtr &binder, const std::vector &filters); @@ -77,11 +77,18 @@ namespace drogon typedef std::shared_ptr SessionPtr; std::unique_ptr> _sessionMapPtr; - bool doFilters(const std::vector &filters, - const HttpRequest& req, + void doFilters(const std::vector &filters, + const HttpRequestPtr& req, const std::function & callback, bool needSetJsessionid, - const std::string &session_id); + const std::string &session_id, + const std::function &missCallback); + void doFilterChain(const std::shared_ptr>> &chain, + const HttpRequestPtr& req, + const std::function & callback, + bool needSetJsessionid, + const std::string &session_id, + const std::function &missCallback); // struct ControllerAndFiltersName { @@ -347,42 +354,56 @@ void HttpAppFrameworkImpl::run() _loop.loop(); } -bool HttpAppFrameworkImpl::doFilters(const std::vector &filters, - const HttpRequest& req, +void HttpAppFrameworkImpl::doFilterChain(const std::shared_ptr>> &chain, + const HttpRequestPtr& req, + const std::function & callback, + bool needSetJsessionid, + const std::string &session_id, + const std::function &missCallback) +{ + if(chain->size()>0) { + auto filter = chain->front(); + chain->pop(); + filter->doFilter(req, [=](HttpResponsePtr res) { + if (needSetJsessionid) + res->addCookie("JSESSIONID", session_id); + callback(*res); + }, [=](){ + doFilterChain(chain,req,callback,needSetJsessionid,session_id,missCallback); + }); + }else{ + missCallback(); + } +} +void HttpAppFrameworkImpl::doFilters(const std::vector &filters, + const HttpRequestPtr& req, const std::function & callback, bool needSetJsessionid, - const std::string &session_id) + const std::string &session_id, + const std::function &missCallback) { LOG_TRACE<<"filters count:"<(DrClassMap::newObject(filter)); + std::shared_ptr>> filterPtrs= + std::make_shared>>(); + for(auto filter:filters) { + auto _object = std::shared_ptr(DrClassMap::newObject(filter)); auto _filter = std::dynamic_pointer_cast(_object); if(_filter) - { - auto resPtr=_filter->doFilter(req); - if(resPtr) - { - if(needSetJsessionid) - resPtr->addCookie("JSESSIONID",session_id); - callback(*resPtr); - return true; - } - } else - { + filterPtrs->push(_filter); + else { LOG_ERROR<<"filter "< & callback) +void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestPtr& req,const std::function & callback) { - LOG_TRACE << "new request:"<"<peerAddr().toIpPort()<<"->"<localAddr().toIpPort(); + LOG_TRACE << "Headers " << req->methodString() << " " << req->path(); #if 1 - const std::map& headers = req.headers(); + const std::map& headers = req->headers(); for (std::map::const_iterator it = headers.begin(); it != headers.end(); ++it) { @@ -390,7 +411,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequest& req,const std::func } LOG_TRACE<<"cookies:"; - auto cookies = req.cookies(); + auto cookies = req->cookies(); for(auto it=cookies.begin();it!=cookies.end();++it) { LOG_TRACE<first<<"="<second; @@ -398,10 +419,10 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequest& req,const std::func #endif - LOG_TRACE << "http path=" << req.path(); - LOG_TRACE << "query: " << req.query() ; + LOG_TRACE << "http path=" << req->path(); + LOG_TRACE << "query: " << req->query() ; - std::string session_id=req.getCookie("JSESSIONID"); + std::string session_id=req->getCookie("JSESSIONID"); bool needSetJsessionid=false; if(_useSession) { @@ -421,7 +442,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequest& req,const std::func ((HttpRequestImpl &)req).setSession((*_sessionMapPtr)[session_id]); } - std::string path = req.path(); + std::string path = req->path(); auto pos = path.rfind("."); if(pos != std::string::npos) { std::string filetype = path.substr(pos + 1); @@ -465,96 +486,98 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequest& req,const std::func /*find simple controller*/ - std::string pathLower(req.path()); + std::string pathLower(req->path()); std::transform(pathLower.begin(),pathLower.end(),pathLower.begin(),tolower); if(_simpCtrlMap.find(pathLower)!=_simpCtrlMap.end()) { auto &filters=_simpCtrlMap[pathLower].filtersName; - if(doFilters(filters,req,callback,needSetJsessionid,session_id)) - return; - const std::string &ctrlName = _simpCtrlMap[pathLower].controllerName; - std::shared_ptr controller; - { - //maybe update controller,so we use lock_guard to protect; - std::lock_guard guard(_simpCtrlMap[pathLower]._mutex); - controller=_simpCtrlMap[pathLower].controller; - if(!controller) + doFilters(filters,req,callback,needSetJsessionid,session_id,[=](){ + const std::string &ctrlName = _simpCtrlMap[pathLower].controllerName; + std::shared_ptr controller; { - auto _object = std::shared_ptr(DrClassMap::newObject(ctrlName)); - controller = std::dynamic_pointer_cast(_object); - _simpCtrlMap[pathLower].controller=controller; + //maybe update controller,so we use lock_guard to protect; + std::lock_guard guard(_simpCtrlMap[pathLower]._mutex); + controller=_simpCtrlMap[pathLower].controller; + if(!controller) + { + auto _object = std::shared_ptr(DrClassMap::newObject(ctrlName)); + controller = std::dynamic_pointer_cast(_object); + _simpCtrlMap[pathLower].controller=controller; + } } - } - if(controller) { - controller->asyncHandleHttpRequest(req, [=](HttpResponse& resp){ - if(needSetJsessionid) - resp.addCookie("JSESSIONID",session_id); - callback(resp); - }); - return; - } else { + if(controller) { + controller->asyncHandleHttpRequest(req, [=](HttpResponse& resp){ + if(needSetJsessionid) + resp.addCookie("JSESSIONID",session_id); + callback(resp); + }); + return; + } else { + + LOG_ERROR << "can't find controller " << ctrlName; + } + }); - LOG_ERROR << "can't find controller " << ctrlName; - } } //find api controller if(_apiRegex.mark_count()>0) { std::smatch result; - if(std::regex_match(req.path(),result,_apiRegex)) + if(std::regex_match(req->path(),result,_apiRegex)) { for(size_t i=1;ipath()&&i<=_apiCtrlVector.size()) { size_t ctlIndex=i-1; auto &binder=_apiCtrlVector[ctlIndex]; LOG_DEBUG<<"got api access,regex="< params(binder.parameterPlaces.size()); - std::smatch r; - if(std::regex_match(req.path(),r,std::regex(binder.pathParameterPattern))) - { - for(size_t j=1;j params(binder.parameterPlaces.size()); + std::smatch r; + if(std::regex_match(req->path(),r,std::regex(binder.pathParameterPattern))) { - size_t place=binder.parameterPlaces[j-1]; - if(place>params.size()) - params.resize(place); - params[place-1]=r[j].str(); - LOG_DEBUG<<"place="<0) - { - auto qureyPara=req.getParameters(); - for(auto parameter:qureyPara) - { - if(binder.queryParametersPlaces.find(parameter.first)!= - binder.queryParametersPlaces.end()) + for(size_t j=1;jparams.size()) params.resize(place); - params[place-1]=parameter.second; + params[place-1]=r[j].str(); + LOG_DEBUG<<"place="< paraList; - for(auto p:params) - { - LOG_DEBUG<0) + { + auto qureyPara=req->getParameters(); + for(auto parameter:qureyPara) + { + if(binder.queryParametersPlaces.find(parameter.first)!= + binder.queryParametersPlaces.end()) + { + auto place=binder.queryParametersPlaces.find(parameter.first)->second; + if(place>params.size()) + params.resize(place); + params[place-1]=parameter.second; + } + } + } + std::list paraList; + for(auto p:params) + { + LOG_DEBUG<handleHttpApiRequest(paraList,req,callback); + return; + }); - binder.binderPtr->handleHttpApiRequest(paraList,req,callback); - return; } } } @@ -568,7 +591,7 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequest& req,const std::func } -void HttpAppFrameworkImpl::readSendFile(const std::string& filePath,const HttpRequest& req, HttpResponse* resp) +void HttpAppFrameworkImpl::readSendFile(const std::string& filePath,const HttpRequestPtr& req, HttpResponse* resp) { //If-Modified-Since: Wed Jun 15 08:57:30 2016 GMT std::ifstream infile(filePath, std::ifstream::binary); @@ -595,7 +618,7 @@ void HttpAppFrameworkImpl::readSendFile(const std::string& filePath,const HttpRe std::string::size_type len=timeStr.length(); std::string lastModified =timeStr.substr(0,len-1)+" GMT"; - std::string modiStr=req.getHeader("If-Modified-Since"); + std::string modiStr=req->getHeader("If-Modified-Since"); if(modiStr!=""&&modiStr==lastModified) { LOG_DEBUG<<"not Modified!"; diff --git a/lib/src/HttpContext.cc b/lib/src/HttpContext.cc index b0a526cc..829429bf 100755 --- a/lib/src/HttpContext.cc +++ b/lib/src/HttpContext.cc @@ -30,12 +30,18 @@ #include using namespace trantor; using namespace drogon; +HttpContext::HttpContext() + : state_(kExpectRequestLine), + res_state_(HttpResponseParseState::kExpectResponseLine), + request_(new HttpRequestImpl) +{ +} bool HttpContext::processRequestLine(const char *begin, const char *end) { bool succeed = false; const char *start = begin; const char *space = std::find(start, end, ' '); - if (space != end && request_.setMethod(start, space)) + if (space != end && request_->setMethod(start, space)) { start = space + 1; space = std::find(start, end, ' '); @@ -44,12 +50,12 @@ bool HttpContext::processRequestLine(const char *begin, const char *end) const char *question = std::find(start, space, '?'); if (question != space) { - request_.setPath(start, question); - request_.setQuery(question + 1, space); + request_->setPath(start, question); + request_->setQuery(question + 1, space); } else { - request_.setPath(start, space); + request_->setPath(start, space); } start = space + 1; succeed = end - start == 8 && std::equal(start, end - 1, "HTTP/1."); @@ -57,11 +63,11 @@ bool HttpContext::processRequestLine(const char *begin, const char *end) { if (*(end - 1) == '1') { - request_.setVersion(HttpRequest::kHttp11); + request_->setVersion(HttpRequest::kHttp11); } else if (*(end - 1) == '0') { - request_.setVersion(HttpRequest::kHttp10); + request_->setVersion(HttpRequest::kHttp10); } else { @@ -89,7 +95,7 @@ bool HttpContext::parseRequest(MsgBuffer *buf) ok = processRequestLine(buf->peek(), crlf); if (ok) { - //request_.setReceiveTime(receiveTime); + //request_->setReceiveTime(receiveTime); buf->retrieveUntil(crlf + 2); state_ = kExpectHeaders; } @@ -111,16 +117,16 @@ bool HttpContext::parseRequest(MsgBuffer *buf) const char *colon = std::find(buf->peek(), crlf, ':'); if (colon != crlf) { - request_.addHeader(buf->peek(), colon, crlf); + request_->addHeader(buf->peek(), colon, crlf); } else { // empty line, end of header - std::string len = request_.getHeader("Content-Length"); + std::string len = request_->getHeader("Content-Length"); LOG_TRACE << "content len=" << len; if (len != "") { - request_.contentLen = atoi(len.c_str()); + request_->contentLen = atoi(len.c_str()); state_ = kExpectBody; } else @@ -138,33 +144,33 @@ bool HttpContext::parseRequest(MsgBuffer *buf) } else if (state_ == kExpectBody) { - //LOG_INFO << "expectBody:len=" << request_.contentLen; + //LOG_INFO << "expectBody:len=" << request_->contentLen; //LOG_INFO << "expectBody:buf=" << buf; if (buf->readableBytes() == 0) { - if (request_.contentLen == 0) + if (request_->contentLen == 0) { state_ = kGotAll; } break; } - if (request_.contentLen >= buf->readableBytes()) + if (request_->contentLen >= buf->readableBytes()) { - request_.contentLen -= buf->readableBytes(); - request_.content_ += std::string(buf->peek(), buf->readableBytes()); + request_->contentLen -= buf->readableBytes(); + request_->content_ += std::string(buf->peek(), buf->readableBytes()); buf->retrieveAll(); } else { - request_.content_ += std::string(buf->peek(), request_.contentLen); - buf->retrieve(request_.contentLen); - request_.contentLen = 0; + request_->content_ += std::string(buf->peek(), request_->contentLen); + buf->retrieve(request_->contentLen); + request_->contentLen = 0; } - if (request_.contentLen == 0) + if (request_->contentLen == 0) { state_ = kGotAll; - LOG_TRACE << "post got all:len=" << request_.content_.length(); - //LOG_INFO<<"content:"<content_; LOG_TRACE << "content(END)"; hasMore = false; } @@ -304,7 +310,7 @@ bool HttpContext::parseResponse(MsgBuffer *buf) } else if (res_state_ == HttpResponseParseState::kExpectBody) { - //LOG_INFO << "expectBody:len=" << request_.contentLen; + //LOG_INFO << "expectBody:len=" << request_->contentLen; //LOG_INFO << "expectBody:buf=" << buf; if (buf->readableBytes() == 0) { @@ -323,14 +329,14 @@ bool HttpContext::parseResponse(MsgBuffer *buf) else { response_._body += std::string(buf->peek(), response_._left_body_length); - buf->retrieve(request_.contentLen); + buf->retrieve(request_->contentLen); response_._left_body_length = 0; } if (response_._left_body_length == 0) { res_state_ = HttpResponseParseState::kGotAll; LOG_TRACE << "post got all:len=" << response_._left_body_length; - //LOG_INFO<<"content:"<content_; LOG_TRACE << "content(END)"; hasMore = false; } diff --git a/lib/src/HttpContext.h b/lib/src/HttpContext.h index f882a0bb..550cd45a 100755 --- a/lib/src/HttpContext.h +++ b/lib/src/HttpContext.h @@ -56,11 +56,8 @@ namespace drogon kGotAll, }; - HttpContext() - : state_(kExpectRequestLine), - res_state_(HttpResponseParseState::kExpectResponseLine) - { - } + HttpContext(); + // default copy-ctor, dtor and assignment are fine @@ -87,8 +84,7 @@ namespace drogon { state_ = kExpectRequestLine; res_state_ = HttpResponseParseState::kExpectResponseLine; - HttpRequestImpl dummy; - request_.swap(dummy); + request_.reset(new HttpRequestImpl); HttpResponseImpl dummy_res; response_.swap(dummy_res); } @@ -99,17 +95,17 @@ namespace drogon response_.clear(); } - const HttpRequest &request() const + const HttpRequestPtr request() const { return request_; } - HttpRequest &request() + HttpRequestPtr request() { return request_; } - HttpRequestImpl &requestImpl() + HttpRequestImplPtr requestImpl() { return request_; } @@ -133,7 +129,7 @@ namespace drogon bool processResponseLine(const char *begin, const char *end); HttpRequestParseState state_; - HttpRequestImpl request_; + HttpRequestImplPtr request_; HttpResponseParseState res_state_; HttpResponseImpl response_; diff --git a/lib/src/HttpRequestImpl.h b/lib/src/HttpRequestImpl.h index 0fb33d4f..a21802a5 100755 --- a/lib/src/HttpRequestImpl.h +++ b/lib/src/HttpRequestImpl.h @@ -356,6 +356,7 @@ namespace drogon }; + typedef std::shared_ptr HttpRequestImplPtr; } diff --git a/lib/src/HttpServer.cc b/lib/src/HttpServer.cc index 1ba612bd..220e368c 100755 --- a/lib/src/HttpServer.cc +++ b/lib/src/HttpServer.cc @@ -35,7 +35,7 @@ using namespace drogon; using namespace trantor; -static void defaultHttpAsyncCallback(const HttpRequest&,const std::function & callback) +static void defaultHttpAsyncCallback(const HttpRequestPtr&,const std::function & callback) { HttpResponseImpl resp; resp.setStatusCode(HttpResponse::k404NotFound); @@ -92,21 +92,21 @@ void HttpServer::onMessage(const TcpConnectionPtr& conn, } if (context->gotAll()) { - context->requestImpl().parsePremeter(); - context->requestImpl().setPeerAddr(conn->peerAddr()); - context->requestImpl().setLocalAddr(conn->lobalAddr()); - context->requestImpl().setReceiveDate(trantor::Date::date()); + context->requestImpl()->parsePremeter(); + context->requestImpl()->setPeerAddr(conn->peerAddr()); + context->requestImpl()->setLocalAddr(conn->lobalAddr()); + context->requestImpl()->setReceiveDate(trantor::Date::date()); onRequest(conn, context->request()); context->reset(); } } -void HttpServer::onRequest(const TcpConnectionPtr& conn, const HttpRequest& req) +void HttpServer::onRequest(const TcpConnectionPtr& conn, const HttpRequestPtr& req) { - const std::string& connection = req.getHeader("Connection"); + const std::string& connection = req->getHeader("Connection"); bool _close = connection == "close" || - (req.getVersion() == HttpRequestImpl::kHttp10 && connection != "Keep-Alive"); + (req->getVersion() == HttpRequestImpl::kHttp10 && connection != "Keep-Alive"); diff --git a/lib/src/HttpServer.h b/lib/src/HttpServer.h index 0eed2200..d7730380 100755 --- a/lib/src/HttpServer.h +++ b/lib/src/HttpServer.h @@ -28,11 +28,12 @@ namespace drogon { class HttpRequest; class HttpResponse; + typedef std::shared_ptr HttpRequestPtr; class HttpServer : trantor::NonCopyable { public: - typedef std::function< void (const HttpRequest&,const std::function&)> HttpAsyncCallback; + typedef std::function< void (const HttpRequestPtr&,const std::function&)> HttpAsyncCallback; HttpServer(EventLoop* loop, const InetAddress& listenAddr, const std::string& name); @@ -63,7 +64,7 @@ namespace drogon void onConnection(const TcpConnectionPtr& conn); void onMessage(const TcpConnectionPtr&, MsgBuffer*); - void onRequest(const TcpConnectionPtr&, const HttpRequest&); + void onRequest(const TcpConnectionPtr&, const HttpRequestPtr &); trantor::TcpServer server_; HttpAsyncCallback httpAsyncCallback_; diff --git a/lib/src/PostFilter.cc b/lib/src/PostFilter.cc index de8ce30e..4abbb451 100755 --- a/lib/src/PostFilter.cc +++ b/lib/src/PostFilter.cc @@ -15,13 +15,16 @@ #include #include "HttpResponseImpl.h" using namespace drogon; -std::shared_ptr PostFilter::doFilter(const HttpRequest& req) +void PostFilter::doFilter(const HttpRequestPtr& req, + const FilterCallback &fcb, + const FilterChainCallback &fccb) { - if(req.method()==HttpRequest::kPost) + if(req->method()==HttpRequest::kPost) { - return nullptr; + fccb(); + return; } auto res=drogon::HttpResponse::notFoundResponse(); - return res; + fcb(res); } \ No newline at end of file diff --git a/lib/src/PutFilter.cc b/lib/src/PutFilter.cc index 816ad0b0..7db81a36 100755 --- a/lib/src/PutFilter.cc +++ b/lib/src/PutFilter.cc @@ -15,14 +15,16 @@ #include #include "HttpResponseImpl.h" using namespace drogon; -std::shared_ptr PutFilter::doFilter(const HttpRequest& req) +void PutFilter::doFilter(const HttpRequestPtr& req, + const FilterCallback &fcb, + const FilterChainCallback &fccb) { - if(req.method()==HttpRequest::kPut) + if(req->method()==HttpRequest::kPut) { - return nullptr; + fccb(); + return; } auto res=drogon::HttpResponse::notFoundResponse(); - - return res; + fcb(res); } \ No newline at end of file