change doFilter interface

This commit is contained in:
antao 2018-08-02 15:38:06 +08:00
parent d1f4ccf3d7
commit 99ba19ebca
32 changed files with 258 additions and 205 deletions

View File

@ -132,7 +132,7 @@ void create_controller::newSimpleControllerHeaderFile(std::ofstream &file,const
file<<indent<<"{\n";
file<<indent<<"public:\n";
//TestController(){}
file<<indent<<" virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)> & callback)override;\n";
file<<indent<<" virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> & callback)override;\n";
file<<indent<<" PATH_LIST_BEGIN\n";
file<<indent<<" //list path definations here;\n";
@ -147,7 +147,7 @@ void create_controller::newSimpleControllerSourceFile(std::ofstream &file,const
file<<"#include \""<<ctlName<<".h\"\n";
if(namespaceName!="")
file<<"using namespace "<<namespaceName<<";\n";
file<<"void "<<ctlName<<"::asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)> & callback)\n";
file<<"void "<<ctlName<<"::asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> & 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<<indent<<"\n";
file<<indent<<"METHOD_LIST_END\n";
file<<indent<<"//your declaration of processing function maybe like this:\n";
file<<indent<<"//void get(const HttpRequest& req,"
file<<indent<<"//void get(const HttpRequestPtr& req,"
"const std::function<void (HttpResponse &)>&callback,int p1,std::string p2);\n";
file<<indent<<"//void your_method_name(const HttpRequest& req,"
file<<indent<<"//void your_method_name(const HttpRequestPtr& req,"
"const std::function<void (HttpResponse &)>&callback,double p1,int p2) const;\n";
indent.resize(indent.length()-4);
file<<indent<<"};\n";

View File

@ -1,6 +1,6 @@
#include "JsonTestController.h"
#include <json/json.h>
void JsonTestController::asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback)
void JsonTestController::asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback)
{
Json::Value json;
json["path"]="json";

View File

@ -7,7 +7,7 @@ class JsonTestController:public drogon::HttpSimpleController<JsonTestController>
{
public:
//TestController(){}
virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback)override;
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback)override;
PATH_LIST_BEGIN
PATH_ADD("/json");

View File

@ -1,10 +1,10 @@
#include "ListParaCtl.h"
void ListParaCtl::asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback)
void ListParaCtl::asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&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);
}

View File

@ -4,7 +4,7 @@ using namespace drogon;
class ListParaCtl:public drogon::HttpSimpleController<ListParaCtl>
{
public:
virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)> &callback)override;
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> &callback)override;
PATH_LIST_BEGIN
//list path definations here;
//PATH_ADD("/path","filter1","filter2",...);

View File

@ -1,6 +1,6 @@
#include "TestController.h"
using namespace example;
void TestController::asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback)
void TestController::asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback)
{
//write your application logic here
auto resp=HttpResponse::newHttpResponse();

View File

@ -5,7 +5,7 @@ namespace example{
class TestController:public drogon::HttpSimpleController<TestController>
{
public:
virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback)override;
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback)override;
PATH_LIST_BEGIN
//list path definations here;
//PATH_ADD("/path","filter1","filter2",...);

View File

@ -1,5 +1,5 @@
#include "TestViewCtl.h"
void TestViewCtl::asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback)
void TestViewCtl::asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback)
{
//write your application logic here
drogon::HttpViewData data;

View File

@ -4,7 +4,7 @@ using namespace drogon;
class TestViewCtl:public drogon::HttpSimpleController<TestViewCtl>
{
public:
virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback)override;
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback)override;
PATH_LIST_BEGIN
//list path definations here;
//PATH_ADD("/path","filter1","filter2",...);

View File

@ -6,29 +6,33 @@
#include <trantor/utils/Date.h>
#include <trantor/utils/Logger.h>
#define VDate "visitDate"
std::shared_ptr<HttpResponse> 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<trantor::Date>(VDate);
auto lastDate=req->session()->get<trantor::Date>(VDate);
LOG_TRACE<<"last:"<<lastDate.toFormattedString(false);
req.session()->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<HttpResponse>(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();
}

View File

@ -9,7 +9,9 @@ using namespace drogon;
class TimeFilter: public drogon::HttpFilter<TimeFilter> {
public:
virtual std::shared_ptr<HttpResponse> doFilter(const HttpRequest& req) override;
virtual void doFilter(const HttpRequestPtr& req,
const FilterCallback &cb,
const FilterChainCallback &ccb) override;
};

View File

@ -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<void (HttpResponse &)>&callback,int p1,std::string p2)
void ApiTest::get(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&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<void (HttpResponse
auto res=HttpResponse::newHttpViewResponse("DynamicListParaView.csp",data);
callback(*res);
}
void ApiTest::your_method_name(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback,double p1,int p2) const
void ApiTest::your_method_name(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback,double p1,int p2) const
{
HttpViewData data;
data.insert("title",std::string("ApiTest::get"));

View File

@ -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<void (HttpResponse &)>&callback,int p1,std::string p2);
void your_method_name(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback,double p1,int p2) const;
void get(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback,int p1,std::string p2);
void your_method_name(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback,double p1,int p2) const;
};
}
}

View File

@ -9,7 +9,7 @@ using namespace drogon;
class A
{
public:
void handle(const HttpRequest& req,
void handle(const HttpRequestPtr& req,
const std::function<void (HttpResponse &)>&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<void (HttpResponse &)>&callback,int p1,int p2)
void operator ()(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&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<void (HttpResponse &)>&callback,int p1,int p2) const
void get(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&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<void (HttpResponse &)>&callback,int p1,int p2) const
void list(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&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<void (HttpResponse &)>&callback,int a,float b){
drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle2/{1}/{2}",[](const HttpRequestPtr&req,const std::function<void (HttpResponse &)>&callback,int a,float b){
LOG_DEBUG<<"int a="<<a;
LOG_DEBUG<<"float b="<<b;
HttpViewData data;
@ -113,7 +113,7 @@ int main()
drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle3/{1}/{2}",b);
A tmp;
std::function<void(const HttpRequest&,const std::function<void (HttpResponse &)>&,int,const std::string &,const std::string &,int)>
std::function<void(const HttpRequestPtr&,const std::function<void (HttpResponse &)>&,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);

View File

@ -22,6 +22,8 @@ namespace drogon
{
public:
DeleteFilter(){}
virtual std::shared_ptr<HttpResponse> doFilter(const HttpRequest& req) override ;
virtual void doFilter(const HttpRequestPtr& req,
const FilterCallback &fcb,
const FilterChainCallback &fccb) override ;
};
}

View File

@ -22,6 +22,8 @@ namespace drogon
{
public:
GetFilter(){}
virtual std::shared_ptr<HttpResponse> doFilter(const HttpRequest& req) override ;
virtual void doFilter(const HttpRequestPtr& req,
const FilterCallback &fcb,
const FilterChainCallback &fccb) override ;
};
}

View File

@ -48,7 +48,7 @@ namespace drogon{
{
public:
virtual void handleHttpApiRequest(std::list<std::string> &pathParameter,
const HttpRequest& req,std::function<void (HttpResponse &)>callback)
const HttpRequestPtr& req,std::function<void (HttpResponse &)>callback)
=0;
virtual size_t paramCount()=0;
virtual ~HttpApiBinderBase(){}
@ -60,7 +60,7 @@ namespace drogon{
public:
typedef FUNCTION FunctionType;
virtual void handleHttpApiRequest(std::list<std::string> &pathParameter,
const HttpRequest& req,std::function<void (HttpResponse &)>callback) override
const HttpRequestPtr& req,std::function<void (HttpResponse &)>callback) override
{
run(pathParameter,req,callback);
}
@ -95,7 +95,7 @@ namespace drogon{
>
typename std::enable_if<(sizeof...(Values) < Boundary), void>::type run(
std::list<std::string> &pathParameter,
const HttpRequest& req,std::function<void (HttpResponse &)>callback,
const HttpRequestPtr& req,std::function<void (HttpResponse &)>callback,
Values&&... values
)
{
@ -124,7 +124,7 @@ namespace drogon{
>
typename std::enable_if<(sizeof...(Values) == Boundary), void>::type run(
std::list<std::string> &pathParameter,
const HttpRequest& req,std::function<void (HttpResponse &)>callback,
const HttpRequestPtr& req,std::function<void (HttpResponse &)>callback,
Values&&... values
)
{
@ -133,7 +133,7 @@ namespace drogon{
template <typename... Values,
bool isClassFunction = traits::isClassFunction>
typename std::enable_if<isClassFunction,void>::type callFunction(
const HttpRequest& req,std::function<void (HttpResponse &)>callback,
const HttpRequestPtr& req,std::function<void (HttpResponse &)>callback,
Values&&... values)
{
static typename traits::class_type obj;
@ -142,7 +142,7 @@ namespace drogon{
template <typename... Values,
bool isClassFunction = traits::isClassFunction>
typename std::enable_if<!isClassFunction,void>::type callFunction(
const HttpRequest& req,std::function<void (HttpResponse &)>callback,
const HttpRequestPtr& req,std::function<void (HttpResponse &)>callback,
Values&&... values)
{
_func(req,callback,std::move(values)...);

View File

@ -21,10 +21,14 @@
namespace drogon
{
typedef std::function<void(HttpResponsePtr)>FilterCallback;
typedef std::function<void()>FilterChainCallback;
class HttpFilterBase:public virtual DrObjectBase
{
public:
virtual std::shared_ptr<HttpResponse> doFilter(const HttpRequest& req)=0;
virtual void doFilter(const HttpRequestPtr& req,
const FilterCallback &fcb,
const FilterChainCallback &fccb)=0;
virtual ~HttpFilterBase(){}
};
template <typename T>

View File

@ -36,7 +36,7 @@ namespace drogon
class HttpSimpleControllerBase:public virtual DrObjectBase
{
public:
virtual void asyncHandleHttpRequest(const HttpRequest& req,const std::function<void (HttpResponse &)> &callback)=0;
virtual void asyncHandleHttpRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> &callback)=0;
virtual ~HttpSimpleControllerBase(){}
};

View File

@ -22,6 +22,8 @@ namespace drogon
{
public:
PostFilter(){}
virtual std::shared_ptr<HttpResponse> doFilter(const HttpRequest& req) override ;
virtual void doFilter(const HttpRequestPtr& req,
const FilterCallback &fcb,
const FilterChainCallback &fccb) override ;
};
}

View File

@ -22,6 +22,8 @@ namespace drogon
{
public:
PutFilter(){}
virtual std::shared_ptr<HttpResponse> doFilter(const HttpRequest& req) override ;
virtual void doFilter(const HttpRequestPtr& req,
const FilterCallback &fcb,
const FilterChainCallback &fccb) override ;
};
}

View File

@ -5,6 +5,7 @@
namespace drogon{
class HttpRequest;
class HttpResponse;
typedef std::shared_ptr<HttpRequest> HttpRequestPtr;
namespace utility {
template<typename> struct FunctionTraits;
@ -54,7 +55,7 @@ namespace drogon{
typename... Arguments
>
struct FunctionTraits<
ReturnType(ClassType::*)(const HttpRequest& req,const std::function<void (HttpResponse &)>&callback,Arguments...) const
ReturnType(ClassType::*)(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback,Arguments...) const
> : FunctionTraits<ReturnType(ClassType::*)(Arguments...)> {
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<void (HttpResponse &)>&callback,Arguments...)
ReturnType(ClassType::*)(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback,Arguments...)
> : FunctionTraits<ReturnType(ClassType::*)(Arguments...)> {
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<void (HttpResponse &)>&callback,Arguments...)
ReturnType(*)(const HttpRequestPtr& req,const std::function<void (HttpResponse &)>&callback,Arguments...)
> : FunctionTraits<ReturnType(*)(Arguments...)> {
static const bool isHTTPApiFunction=true;

View File

@ -15,14 +15,15 @@
#include <drogon/DeleteFilter.h>
#include "HttpResponseImpl.h"
using namespace drogon;
std::shared_ptr<HttpResponse> 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);
}

View File

@ -15,14 +15,15 @@
#include <drogon/GetFilter.h>
#include "HttpResponseImpl.h"
using namespace drogon;
std::shared_ptr<HttpResponse> 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);
}

View File

@ -64,8 +64,8 @@ namespace drogon
virtual trantor::EventLoop *loop() override;
private:
std::vector<std::tuple<std::string,uint16_t,bool>> _listeners;
void onAsyncRequest(const HttpRequest& req,const std::function<void (HttpResponse &)> & callback);
void readSendFile(const std::string& filePath,const HttpRequest& req, HttpResponse* resp);
void onAsyncRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> & callback);
void readSendFile(const std::string& filePath,const HttpRequestPtr& req, HttpResponse* resp);
void addApiPath(const std::string &path,
const HttpApiBinderBasePtr &binder,
const std::vector<std::string> &filters);
@ -77,11 +77,18 @@ namespace drogon
typedef std::shared_ptr<Session> SessionPtr;
std::unique_ptr<CacheMap<std::string,SessionPtr>> _sessionMapPtr;
bool doFilters(const std::vector<std::string> &filters,
const HttpRequest& req,
void doFilters(const std::vector<std::string> &filters,
const HttpRequestPtr& req,
const std::function<void (HttpResponse &)> & callback,
bool needSetJsessionid,
const std::string &session_id);
const std::string &session_id,
const std::function<void ()> &missCallback);
void doFilterChain(const std::shared_ptr<std::queue<std::shared_ptr<HttpFilterBase>>> &chain,
const HttpRequestPtr& req,
const std::function<void (HttpResponse &)> & callback,
bool needSetJsessionid,
const std::string &session_id,
const std::function<void ()> &missCallback);
//
struct ControllerAndFiltersName
{
@ -347,42 +354,56 @@ void HttpAppFrameworkImpl::run()
_loop.loop();
}
bool HttpAppFrameworkImpl::doFilters(const std::vector<std::string> &filters,
const HttpRequest& req,
void HttpAppFrameworkImpl::doFilterChain(const std::shared_ptr<std::queue<std::shared_ptr<HttpFilterBase>>> &chain,
const HttpRequestPtr& req,
const std::function<void (HttpResponse &)> & callback,
bool needSetJsessionid,
const std::string &session_id,
const std::function<void ()> &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<std::string> &filters,
const HttpRequestPtr& req,
const std::function<void (HttpResponse &)> & callback,
bool needSetJsessionid,
const std::string &session_id)
const std::string &session_id,
const std::function<void ()> &missCallback)
{
LOG_TRACE<<"filters count:"<<filters.size();
for(auto filter:filters)
{
auto _object=std::shared_ptr<DrObjectBase>(DrClassMap::newObject(filter));
std::shared_ptr<std::queue<std::shared_ptr<HttpFilterBase>>> filterPtrs=
std::make_shared<std::queue<std::shared_ptr<HttpFilterBase>>>();
for(auto filter:filters) {
auto _object = std::shared_ptr<DrObjectBase>(DrClassMap::newObject(filter));
auto _filter = std::dynamic_pointer_cast<HttpFilterBase>(_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 "<<filter<<" not found";
}
}
return false;
doFilterChain(filterPtrs,req,callback,needSetJsessionid,session_id,missCallback);
}
void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequest& req,const std::function<void (HttpResponse &)> & callback)
void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestPtr& req,const std::function<void (HttpResponse &)> & callback)
{
LOG_TRACE << "new request:"<<req.peerAddr().toIpPort()<<"->"<<req.localAddr().toIpPort();
LOG_TRACE << "Headers " << req.methodString() << " " << req.path();
LOG_TRACE << "new request:"<<req->peerAddr().toIpPort()<<"->"<<req->localAddr().toIpPort();
LOG_TRACE << "Headers " << req->methodString() << " " << req->path();
#if 1
const std::map<std::string, std::string>& headers = req.headers();
const std::map<std::string, std::string>& headers = req->headers();
for (std::map<std::string, std::string>::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<<it->first<<"="<<it->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<HttpSimpleControllerBase> controller;
{
//maybe update controller,so we use lock_guard to protect;
std::lock_guard<std::mutex> 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<HttpSimpleControllerBase> controller;
{
auto _object = std::shared_ptr<DrObjectBase>(DrClassMap::newObject(ctrlName));
controller = std::dynamic_pointer_cast<HttpSimpleControllerBase>(_object);
_simpCtrlMap[pathLower].controller=controller;
//maybe update controller,so we use lock_guard to protect;
std::lock_guard<std::mutex> guard(_simpCtrlMap[pathLower]._mutex);
controller=_simpCtrlMap[pathLower].controller;
if(!controller)
{
auto _object = std::shared_ptr<DrObjectBase>(DrClassMap::newObject(ctrlName));
controller = std::dynamic_pointer_cast<HttpSimpleControllerBase>(_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;i<result.size();i++)
{
if(result[i].str().empty())
continue;
if(result[i].str()==req.path()&&i<=_apiCtrlVector.size())
if(result[i].str()==req->path()&&i<=_apiCtrlVector.size())
{
size_t ctlIndex=i-1;
auto &binder=_apiCtrlVector[ctlIndex];
LOG_DEBUG<<"got api access,regex="<<binder.pathParameterPattern;
auto &filters=binder.filtersName;
if(doFilters(filters,req,callback,needSetJsessionid,session_id))
return;
std::vector<std::string> params(binder.parameterPlaces.size());
std::smatch r;
if(std::regex_match(req.path(),r,std::regex(binder.pathParameterPattern)))
{
for(size_t j=1;j<r.size();j++)
doFilters(filters,req,callback,needSetJsessionid,session_id,[=](){
std::vector<std::string> 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="<<place<<" para:"<<params[place-1];
}
}
if(binder.queryParametersPlaces.size()>0)
{
auto qureyPara=req.getParameters();
for(auto parameter:qureyPara)
{
if(binder.queryParametersPlaces.find(parameter.first)!=
binder.queryParametersPlaces.end())
for(size_t j=1;j<r.size();j++)
{
auto place=binder.queryParametersPlaces[parameter.first];
size_t place=binder.parameterPlaces[j-1];
if(place>params.size())
params.resize(place);
params[place-1]=parameter.second;
params[place-1]=r[j].str();
LOG_DEBUG<<"place="<<place<<" para:"<<params[place-1];
}
}
}
std::list<std::string> paraList;
for(auto p:params)
{
LOG_DEBUG<<p;
paraList.push_back(std::move(p));
}
if(binder.queryParametersPlaces.size()>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<std::string> paraList;
for(auto p:params)
{
LOG_DEBUG<<p;
paraList.push_back(std::move(p));
}
binder.binderPtr->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!";

View File

@ -30,12 +30,18 @@
#include <iostream>
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:"<<request_.content_;
LOG_TRACE << "post got all:len=" << request_->content_.length();
//LOG_INFO<<"content:"<<request_->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:"<<request_.content_;
//LOG_INFO<<"content:"<<request_->content_;
LOG_TRACE << "content(END)";
hasMore = false;
}

View File

@ -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_;

View File

@ -356,6 +356,7 @@ namespace drogon
};
typedef std::shared_ptr<HttpRequestImpl> HttpRequestImplPtr;
}

View File

@ -35,7 +35,7 @@ using namespace drogon;
using namespace trantor;
static void defaultHttpAsyncCallback(const HttpRequest&,const std::function<void( HttpResponse& resp)> & callback)
static void defaultHttpAsyncCallback(const HttpRequestPtr&,const std::function<void( HttpResponse& resp)> & 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");

View File

@ -28,11 +28,12 @@ namespace drogon
{
class HttpRequest;
class HttpResponse;
typedef std::shared_ptr<HttpRequest> HttpRequestPtr;
class HttpServer : trantor::NonCopyable
{
public:
typedef std::function< void (const HttpRequest&,const std::function<void (HttpResponse &)>&)> HttpAsyncCallback;
typedef std::function< void (const HttpRequestPtr&,const std::function<void (HttpResponse &)>&)> 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_;

View File

@ -15,13 +15,16 @@
#include <drogon/PostFilter.h>
#include "HttpResponseImpl.h"
using namespace drogon;
std::shared_ptr<HttpResponse> 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);
}

View File

@ -15,14 +15,16 @@
#include <drogon/PutFilter.h>
#include "HttpResponseImpl.h"
using namespace drogon;
std::shared_ptr<HttpResponse> 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);
}