diff --git a/lib/inc/drogon/HttpAppFramework.h b/lib/inc/drogon/HttpAppFramework.h index 4ddd32301f..80af4689f7 100644 --- a/lib/inc/drogon/HttpAppFramework.h +++ b/lib/inc/drogon/HttpAppFramework.h @@ -79,6 +79,12 @@ using DefaultHandler = std::function &&)>; using HttpHandlerInfo = std::tuple; +enum class SessionMode +{ + kAuto = 0, + kManual = 1 +}; + #ifdef __cpp_impl_coroutine class HttpAppFramework; @@ -913,6 +919,16 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable idGeneratorCallback); } + /// Set session mode. + /** + * @param mode The number of seconds which is the timeout of a session + * + * @note + * + * This operation can be performed by an option in the configuration file. + */ + virtual HttpAppFramework &setSessionMode(SessionMode mode) = 0; + /// Register an advice called when starting a new session. /** * @param advice is called with the session id. diff --git a/lib/inc/drogon/HttpRequest.h b/lib/inc/drogon/HttpRequest.h index 24d8c7579d..f386f4759d 100644 --- a/lib/inc/drogon/HttpRequest.h +++ b/lib/inc/drogon/HttpRequest.h @@ -292,6 +292,9 @@ class DROGON_EXPORT HttpRequest return session(); } + /// Get the session to which the request belongs, create if not exists + virtual const SessionPtr &getOrCreateSession() = 0; + /// Get the attributes store, users can add/get any type of data to/from /// this store virtual const AttributesPtr &attributes() const = 0; diff --git a/lib/src/ConfigLoader.cc b/lib/src/ConfigLoader.cc index 3940811b6b..ba1c84e940 100644 --- a/lib/src/ConfigLoader.cc +++ b/lib/src/ConfigLoader.cc @@ -276,7 +276,19 @@ static void loadApp(const Json::Value &app) maxAge); } else + { drogon::app().disableSession(); + } + auto sessionMode = app.get("session_mode", "auto").asString(); + if (sessionMode == "auto" || sessionMode == "AUTO") + { + drogon::app().setSessionMode(SessionMode::kAuto); + } + else + { + drogon::app().setSessionMode(SessionMode::kManual); + } + // document root auto documentRoot = app.get("document_root", "").asString(); if (documentRoot != "") diff --git a/lib/src/HttpAppFrameworkImpl.cc b/lib/src/HttpAppFrameworkImpl.cc index 35448bad2f..ddc1ba7385 100644 --- a/lib/src/HttpAppFrameworkImpl.cc +++ b/lib/src/HttpAppFrameworkImpl.cc @@ -712,6 +712,10 @@ void HttpAppFrameworkImpl::findSessionForRequest(const HttpRequestImplPtr &req) bool needSetSessionid = false; if (sessionId.empty()) { + if (sessionMode_ != SessionMode::kAuto) + { + return; + } sessionId = sessionIdGeneratorCallback_(); needSetSessionid = true; } @@ -720,6 +724,15 @@ void HttpAppFrameworkImpl::findSessionForRequest(const HttpRequestImplPtr &req) } } +void HttpAppFrameworkImpl::createSessionForRequest(HttpRequestImpl *req) +{ + if (useSession_) + { + std::string sessionId = sessionIdGeneratorCallback_(); + req->setSession(sessionManagerPtr_->getSession(sessionId, true)); + } +} + std::vector HttpAppFrameworkImpl::getHandlersInfo() const { return HttpControllersRouter::instance().getHandlersInfo(); diff --git a/lib/src/HttpAppFrameworkImpl.h b/lib/src/HttpAppFrameworkImpl.h index 498482a5ff..5d624f228d 100644 --- a/lib/src/HttpAppFrameworkImpl.h +++ b/lib/src/HttpAppFrameworkImpl.h @@ -215,6 +215,11 @@ class HttpAppFrameworkImpl final : public HttpAppFramework return *this; } + HttpAppFramework &setSessionMode(SessionMode mode) override + { + sessionMode_ = mode; + } + HttpAppFramework ®isterSessionStartAdvice( const AdviceStartSessionCallback &advice) override { @@ -656,8 +661,8 @@ class HttpAppFrameworkImpl final : public HttpAppFramework // should return unsigned type! int64_t getConnectionCount() const override; - // TODO: move session related codes to its own singleton class void findSessionForRequest(const HttpRequestImplPtr &req); + void createSessionForRequest(HttpRequestImpl *req); HttpResponsePtr handleSessionForResponse(const HttpRequestImplPtr &req, const HttpResponsePtr &resp); @@ -693,6 +698,7 @@ class HttpAppFrameworkImpl final : public HttpAppFramework int sessionMaxAge_{-1}; size_t idleConnectionTimeout_{60}; bool useSession_{false}; + SessionMode sessionMode_{SessionMode::kAuto}; std::string serverHeader_{"server: drogon/" + drogon::getVersion() + "\r\n"}; diff --git a/lib/src/HttpRequestImpl.cc b/lib/src/HttpRequestImpl.cc index dc6f68f7e8..2a847ac074 100644 --- a/lib/src/HttpRequestImpl.cc +++ b/lib/src/HttpRequestImpl.cc @@ -1114,3 +1114,12 @@ void HttpRequestImpl::quitStreamMode() assert(!streamReaderPtr_); streamStatus_ = ReqStreamStatus::None; } + +const SessionPtr &HttpRequestImpl::getOrCreateSession() +{ + if (sessionPtr_) + return sessionPtr_; + + HttpAppFrameworkImpl::instance().createSessionForRequest(this); + return sessionPtr_; +} diff --git a/lib/src/HttpRequestImpl.h b/lib/src/HttpRequestImpl.h index 966ef92b78..b8c03f8fab 100644 --- a/lib/src/HttpRequestImpl.h +++ b/lib/src/HttpRequestImpl.h @@ -470,6 +470,8 @@ class HttpRequestImpl : public HttpRequest return sessionPtr_; } + const SessionPtr &getOrCreateSession() override; + void setSession(const SessionPtr &session) { sessionPtr_ = session; diff --git a/lib/src/HttpServer.cc b/lib/src/HttpServer.cc index e11b0949c3..a8b8b722fc 100644 --- a/lib/src/HttpServer.cc +++ b/lib/src/HttpServer.cc @@ -426,7 +426,6 @@ void HttpServer::onHttpRequest( return; } - // TODO: move session related codes to its own singleton class HttpAppFrameworkImpl::instance().findSessionForRequest(req); // pre-routing aop auto &aop = AopAdvice::instance();