From 53179826254fc3173ed9520df1b74d27444a49a2 Mon Sep 17 00:00:00 2001 From: antao Date: Thu, 11 Oct 2018 19:11:49 +0800 Subject: [PATCH] Modify HttpAppFrameworkImpl --- lib/src/HttpAppFrameworkImpl.cc | 64 +++++++++++++----- lib/src/HttpResponseImpl.cc | 116 +++++++++++++++++--------------- lib/src/HttpResponseImpl.h | 7 ++ 3 files changed, 117 insertions(+), 70 deletions(-) diff --git a/lib/src/HttpAppFrameworkImpl.cc b/lib/src/HttpAppFrameworkImpl.cc index 8b2c5861..d7eccdfa 100755 --- a/lib/src/HttpAppFrameworkImpl.cc +++ b/lib/src/HttpAppFrameworkImpl.cc @@ -770,9 +770,21 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestPtr& req,const std::f if(controller) { - if(responsePtr&&!needSetJsessionid) + if(responsePtr) { - callback(responsePtr); + //use cached response! + LOG_TRACE<<"Use cached response"; + if(!needSetJsessionid) + callback(responsePtr); + else + { + auto newResp=std::make_shared + (*std::dynamic_pointer_cast(responsePtr)); + newResp->addCookie("JSESSIONID",session_id); + newResp->setExpiredTime(-1); + callback(newResp); + } + return; } else { @@ -780,9 +792,14 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestPtr& req,const std::f if(needSetJsessionid) resp->addCookie("JSESSIONID",session_id); callback(resp); - if(resp->expiredTime()>=0&&!needSetJsessionid) + if(resp->expiredTime()>=0) { //cache the response; + if(needSetJsessionid) + { + resp->removeCookie("JSESSIONID"); + std::dynamic_pointer_cast(resp)->makeHeaderString(); + } std::lock_guard guard(_simpCtrlMap[pathLower]._mutex); _responseCacheMap->insert(pathLower,resp,resp->expiredTime()); _simpCtrlMap[pathLower].responsePtr=resp; @@ -818,21 +835,29 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestPtr& req,const std::f doFilters(filters,req,callback,needSetJsessionid,session_id,[=](){ auto &binder=_apiCtrlVector[ctlIndex]; - if(!needSetJsessionid) + + HttpResponsePtr responsePtr; { - HttpResponsePtr responsePtr; - { - std::lock_guard guard(*(binder.binderMtx)); - responsePtr=binder.responsePtr.lock(); - } - if(responsePtr) - { - //use cached response! - LOG_TRACE<<"Use cached response"; - callback(responsePtr); - return; - } + std::lock_guard guard(*(binder.binderMtx)); + responsePtr=binder.responsePtr.lock(); } + if(responsePtr) + { + //use cached response! + LOG_TRACE<<"Use cached response"; + if(!needSetJsessionid) + callback(responsePtr); + else + { + auto newResp=std::make_shared + (*std::dynamic_pointer_cast(responsePtr)); + newResp->addCookie("JSESSIONID",session_id); + newResp->setExpiredTime(-1); + callback(newResp); + } + return; + } + std::vector params(binder.parameterPlaces.size()); std::smatch r; if(std::regex_match(req->path(),r,std::regex(binder.pathParameterPattern))) @@ -873,9 +898,14 @@ void HttpAppFrameworkImpl::onAsyncRequest(const HttpRequestPtr& req,const std::f if(needSetJsessionid) resp->addCookie("JSESSIONID",session_id); callback(resp); - if(resp->expiredTime()>=0&&!needSetJsessionid) + if(resp->expiredTime()>=0) { //cache the response; + if(needSetJsessionid) + { + resp->removeCookie("JSESSIONID"); + std::dynamic_pointer_cast(resp)->makeHeaderString(); + } std::lock_guard guard(*(_apiCtrlVector[ctlIndex].binderMtx)); _responseCacheMap->insert(_apiCtrlVector[ctlIndex].pathParameterPattern,resp,resp->expiredTime()); _apiCtrlVector[ctlIndex].responsePtr=resp; diff --git a/lib/src/HttpResponseImpl.cc b/lib/src/HttpResponseImpl.cc index fddec094..0c51412b 100755 --- a/lib/src/HttpResponseImpl.cc +++ b/lib/src/HttpResponseImpl.cc @@ -312,62 +312,72 @@ std::string HttpResponseImpl::web_response_code_to_string(int code) return "Undefined Error"; } } +void HttpResponseImpl::makeHeaderString(MsgBuffer* output) const +{ + char buf[64]; + snprintf(buf, sizeof buf, "HTTP/1.1 %d ", _statusCode); + output->append(buf); + output->append(_statusMessage); + output->append("\r\n"); + if (_sendfileName.empty()) { + snprintf(buf, sizeof buf, "Content-Length: %lu\r\n", _body.size()); + } else { + struct stat filestat; + if (stat(_sendfileName.c_str(), &filestat) < 0) { + LOG_SYSERR << _sendfileName << " stat error"; + return; + } +#ifdef __linux__ + snprintf(buf, sizeof buf, "Content-Length: %ld\r\n",filestat.st_size); +#else + snprintf(buf, sizeof buf, "Content-Length: %lld\r\n", filestat.st_size); +#endif + } + + output->append(buf); + if (_headers.find("Connection") == _headers.end()) { + if (_closeConnection) { + output->append("Connection: close\r\n"); + } else { + + //output->append("Connection: Keep-Alive\r\n"); + } + } + + + for (auto it = _headers.begin(); + it != _headers.end(); + ++it) { + output->append(it->first); + output->append(": "); + output->append(it->second); + output->append("\r\n"); + } + + output->append("Server: drogon/"); + output->append(drogon::getVersion()); + output->append("\r\n"); + + if(_cookies.size() > 0) { + for(auto it = _cookies.begin(); it != _cookies.end(); it++) { + + output->append(it->second.cookieString()); + } + } + + if(_expriedTime>=0) + _fullHeaderString=std::string(output->peek(),output->readableBytes()); +} +void HttpResponseImpl::makeHeaderString() const +{ + assert(_expriedTime>=0); + MsgBuffer buffer; + makeHeaderString(&buffer); +} void HttpResponseImpl::appendToBuffer(MsgBuffer* output) const { if(_fullHeaderString.empty()) { - char buf[64]; - snprintf(buf, sizeof buf, "HTTP/1.1 %d ", _statusCode); - output->append(buf); - output->append(_statusMessage); - output->append("\r\n"); - if (_sendfileName.empty()) { - snprintf(buf, sizeof buf, "Content-Length: %lu\r\n", _body.size()); - } else { - struct stat filestat; - if (stat(_sendfileName.c_str(), &filestat) < 0) { - LOG_SYSERR << _sendfileName << " stat error"; - return; - } -#ifdef __linux__ - snprintf(buf, sizeof buf, "Content-Length: %ld\r\n",filestat.st_size); -#else - snprintf(buf, sizeof buf, "Content-Length: %lld\r\n", filestat.st_size); -#endif - } - - output->append(buf); - if (_headers.find("Connection") == _headers.end()) { - if (_closeConnection) { - output->append("Connection: close\r\n"); - } else { - - //output->append("Connection: Keep-Alive\r\n"); - } - } - - - for (auto it = _headers.begin(); - it != _headers.end(); - ++it) { - output->append(it->first); - output->append(": "); - output->append(it->second); - output->append("\r\n"); - } - - output->append("Server: drogon/"); - output->append(drogon::getVersion()); - output->append("\r\n"); - - if(_cookies.size() > 0) { - for(auto it = _cookies.begin(); it != _cookies.end(); it++) { - - output->append(it->second.cookieString()); - } - } - - if(_expriedTime>=0) - _fullHeaderString=std::string(output->peek(),output->readableBytes()); + makeHeaderString(output); } else { diff --git a/lib/src/HttpResponseImpl.h b/lib/src/HttpResponseImpl.h index 594327bb..a5273688 100755 --- a/lib/src/HttpResponseImpl.h +++ b/lib/src/HttpResponseImpl.h @@ -186,16 +186,19 @@ namespace drogon virtual void addCookie(const std::string& key, const std::string& value) override { _cookies.insert(std::make_pair(key,Cookie(key,value))); + _fullHeaderString.clear(); } virtual void addCookie(const Cookie &cookie) override { _cookies.insert(std::make_pair(cookie.key(),cookie)); + _fullHeaderString.clear(); } virtual void removeCookie(const std::string& key) override { _cookies.erase(key); + _fullHeaderString.clear(); } virtual void setBody(const std::string& body) override @@ -218,6 +221,7 @@ namespace drogon _statusCode = kUnknown; _v = kHttp11; _statusMessage.clear(); + _fullHeaderString.clear(); _headers.clear(); _cookies.clear(); _body.clear(); @@ -286,6 +290,7 @@ namespace drogon void setSendfile(const std::string &filename){ _sendfileName=filename; } + void makeHeaderString() const; protected: static std::string web_content_type_to_string(uint8_t contenttype); static const std::string web_content_type_and_charset_to_string(uint8_t contenttype, @@ -293,6 +298,8 @@ namespace drogon static std::string web_response_code_to_string(int code); + void makeHeaderString(MsgBuffer* output) const; + private: std::map _headers; std::map _cookies;