Skip to content

Commit

Permalink
add save anon session feature
Browse files Browse the repository at this point in the history
  • Loading branch information
juanetch committed Jan 19, 2022
1 parent bbc3161 commit 6ed18d3
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 60 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,6 @@ set(private_headers
lib/src/impl_forwards.h
lib/src/ListenerManager.h
lib/src/PluginsManager.h
lib/src/SessionManager.h
lib/src/SpinLock.h
lib/src/StaticFileRouter.h
lib/src/TaskTimeoutFlag.h
Expand Down Expand Up @@ -516,6 +515,7 @@ set(DROGON_HEADERS
lib/inc/drogon/MultiPart.h
lib/inc/drogon/NotFound.h
lib/inc/drogon/Session.h
lib/inc/drogon/SessionManager.h
lib/inc/drogon/UploadFile.h
lib/inc/drogon/WebSocketClient.h
lib/inc/drogon/WebSocketConnection.h
Expand Down
1 change: 1 addition & 0 deletions config.example.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
//enable_session: False by default
"enable_session": true,
"session_timeout": 0,
"session_save_anon": true,
//document_root: Root path of HTTP document, defaut path is ./
"document_root": "./",
//home_page: Set the HTML file of the home page, the default value is "index.html"
Expand Down
15 changes: 15 additions & 0 deletions lib/inc/drogon/HttpAppFramework.h
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,21 @@ class DROGON_EXPORT HttpAppFramework : public trantor::NonCopyable
*/
virtual HttpAppFramework &disableSession() = 0;

/// Enable saving of anonymous sessions.
/**
*
* @note
* Saving of anonymous sessions is disabled by default
*/
virtual HttpAppFramework &enableSaveAnonSession() = 0;

/// Disable saving of anonymous sessions.
/**
* @note
* Saving of anonymous sessions is disabled by default
*/
virtual HttpAppFramework &disableSaveAnonSession() = 0;

/// Set the root path of HTTP document, default path is ./
/**
* @note
Expand Down
8 changes: 8 additions & 0 deletions lib/inc/drogon/HttpRequest.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <drogon/DrClassMap.h>
#include <drogon/HttpTypes.h>
#include <drogon/Session.h>
#include <drogon/SessionManager.h>
#include <drogon/Attribute.h>
#include <drogon/UploadFile.h>
#include <json/json.h>
Expand Down Expand Up @@ -255,6 +256,13 @@ class DROGON_EXPORT HttpRequest
return session();
}

/// Set the session to request through access to session manager unique
/// pointer
virtual void setSession(const SessionPtr &session) = 0;
virtual bool setSession() = 0;
// (httpappframework lives longer than httresponse)
virtual void setSessionManager(SessionManager *sessionManagerPtr_) = 0;

/// Get the attributes store, users can add/get any type of data to/from
/// this store
virtual const AttributesPtr &attributes() const = 0;
Expand Down
File renamed without changes.
11 changes: 11 additions & 0 deletions lib/src/ConfigLoader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,18 @@ static void loadApp(const Json::Value &app)
auto enableSession = app.get("enable_session", false).asBool();
auto timeout = app.get("session_timeout", 0).asUInt64();
if (enableSession)
{
drogon::app().enableSession(timeout);
auto saveAnonSession = app.get("session_save_anon", true).asBool();
if (saveAnonSession)
{
drogon::app().enableSaveAnonSession();
}
else
{
drogon::app().disableSaveAnonSession();
}
}
else
drogon::app().disableSession();
// document root
Expand Down
89 changes: 60 additions & 29 deletions lib/src/HttpAppFrameworkImpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
#include "PluginsManager.h"
#include "ListenerManager.h"
#include "SharedLibManager.h"
#include "SessionManager.h"
#include <drogon/SessionManager.h>
#include "DbClientManager.h"
#include "RedisClientManager.h"
#include <drogon/config.h>
Expand Down Expand Up @@ -682,8 +682,18 @@ void HttpAppFrameworkImpl::findSessionForRequest(const HttpRequestImplPtr &req)
bool needSetJsessionid = false;
if (sessionId.empty())
{
sessionId = utils::getUuid();
needSetJsessionid = true;
if (saveAnonSession_)
{
sessionId = utils::getUuid();
needSetJsessionid = true;
}
else
{
// attach SessionManagerPtr to allow possibility of creating
// session
req->setSessionManager(sessionManagerPtr_.get());
return;
}
}
req->setSession(
sessionManagerPtr_->getSession(sessionId, needSetJsessionid));
Expand Down Expand Up @@ -746,48 +756,69 @@ void HttpAppFrameworkImpl::callCallback(
if (useSession_)
{
auto &sessionPtr = req->getSession();
assert(sessionPtr);
if (sessionPtr->needToChangeSessionId())
if (sessionPtr)
{
sessionManagerPtr_->changeSessionId(sessionPtr);
}
if (sessionPtr->needSetToClient())
{
if (resp->expiredTime() >= 0)
if (sessionPtr->needToChangeSessionId())
{
sessionManagerPtr_->changeSessionId(sessionPtr);
}
if (sessionPtr->needSetToClient())
{
if (resp->expiredTime() >= 0)
{
auto newResp = std::make_shared<HttpResponseImpl>(
*static_cast<HttpResponseImpl *>(resp.get()));
newResp->setExpiredTime(-1); // make it temporary
auto jsessionid =
Cookie("JSESSIONID", sessionPtr->sessionId());
jsessionid.setPath("/");
newResp->addCookie(std::move(jsessionid));
sessionPtr->hasSet();
callback(newResp);
return;
}
else
{
auto jsessionid =
Cookie("JSESSIONID", sessionPtr->sessionId());
jsessionid.setPath("/");
resp->addCookie(std::move(jsessionid));
sessionPtr->hasSet();
callback(resp);
return;
}
}
else if (resp->version() != req->version())
{
auto newResp = std::make_shared<HttpResponseImpl>(
*static_cast<HttpResponseImpl *>(resp.get()));
newResp->setVersion(req->version());
newResp->setExpiredTime(-1); // make it temporary
auto jsessionid = Cookie("JSESSIONID", sessionPtr->sessionId());
jsessionid.setPath("/");
newResp->addCookie(std::move(jsessionid));
sessionPtr->hasSet();
callback(newResp);
return;
}
else
{
auto jsessionid = Cookie("JSESSIONID", sessionPtr->sessionId());
jsessionid.setPath("/");
resp->addCookie(std::move(jsessionid));
sessionPtr->hasSet();
callback(resp);
return;
}
}
else if (resp->version() != req->version())
{
auto newResp = std::make_shared<HttpResponseImpl>(
*static_cast<HttpResponseImpl *>(resp.get()));
newResp->setVersion(req->version());
newResp->setExpiredTime(-1); // make it temporary
callback(newResp);
return;
}
else
{
callback(resp);
return;
if (resp->expiredTime() >= 0 && resp->version() != req->version())
{
auto newResp = std::make_shared<HttpResponseImpl>(
*static_cast<HttpResponseImpl *>(resp.get()));
newResp->setVersion(req->version());
newResp->setExpiredTime(-1); // make it temporary
callback(newResp);
return;
}
else
{
callback(resp);
return;
}
}
}
else
Expand Down
11 changes: 11 additions & 0 deletions lib/src/HttpAppFrameworkImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,16 @@ class HttpAppFrameworkImpl final : public HttpAppFramework
useSession_ = false;
return *this;
}
HttpAppFramework &enableSaveAnonSession() override
{
saveAnonSession_ = true;
return *this;
}
HttpAppFramework &disableSaveAnonSession() override
{
saveAnonSession_ = false;
return *this;
}
const std::string &getDocumentRoot() const override
{
return rootPath_;
Expand Down Expand Up @@ -580,6 +590,7 @@ class HttpAppFrameworkImpl final : public HttpAppFramework
size_t sessionTimeout_{0};
size_t idleConnectionTimeout_{60};
bool useSession_{false};
bool saveAnonSession_{true};
std::string serverHeader_{"server: drogon/" + drogon::getVersion() +
"\r\n"};

Expand Down
20 changes: 20 additions & 0 deletions lib/src/HttpRequestImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <drogon/utils/Utilities.h>
#include <drogon/HttpRequest.h>
#include <drogon/utils/Utilities.h>
#include <drogon/SessionManager.h>
#include <trantor/net/EventLoop.h>
#include <trantor/net/InetAddress.h>
#include <trantor/utils/Logger.h>
Expand Down Expand Up @@ -358,6 +359,24 @@ class HttpRequestImpl : public HttpRequest
sessionPtr_ = session;
}

bool setSession()
{
if (sessionManagerPtr_)
{
std::string sessionId = utils::getUuid();
bool needSetJsessionid = true;
sessionPtr_ =
sessionManagerPtr_->getSession(sessionId, needSetJsessionid);
return true;
}
return false;
}

void setSessionManager(SessionManager *sessionManagerPtr)
{
sessionManagerPtr_ = sessionManagerPtr;
}

virtual const AttributesPtr &attributes() const override
{
if (!attributesPtr_)
Expand Down Expand Up @@ -542,6 +561,7 @@ class HttpRequestImpl : public HttpRequest
mutable ContentType contentType_{CT_TEXT_PLAIN};
mutable bool flagForParsingContentType_{false};
mutable std::string contentTypeString_;
SessionManager *sessionManagerPtr_;
};

using HttpRequestImplPtr = std::shared_ptr<HttpRequestImpl>;
Expand Down
2 changes: 1 addition & 1 deletion lib/src/SessionManager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*
*/

#include "SessionManager.h"
#include <drogon/SessionManager.h>
#include <drogon/utils/Utilities.h>

using namespace drogon;
Expand Down
32 changes: 7 additions & 25 deletions lib/tests/integration_test/client/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,6 @@ Cookie sessionID;

void doTest(const HttpClientPtr &client, std::shared_ptr<test::Case> TEST_CTX)
{
/// Get cookie
if (!sessionID)
{
auto req = HttpRequest::newHttpRequest();
req->setMethod(drogon::Get);
req->setPath("/");
std::promise<int> waitCookie;
auto f = waitCookie.get_future();
client->sendRequest(req,
[client, &waitCookie, TEST_CTX](
ReqResult result, const HttpResponsePtr &resp) {
REQUIRE(result == ReqResult::Ok);

auto &id = resp->getCookie("JSESSIONID");
REQUIRE(id);

sessionID = id;
client->addCookie(id);
waitCookie.set_value(1);
});
f.get();
}
else
client->addCookie(sessionID);

/// Test begin advice
auto req = HttpRequest::newHttpRequest();
req->setMethod(drogon::Get);
Expand All @@ -86,6 +61,13 @@ void doTest(const HttpClientPtr &client, std::shared_ptr<test::Case> TEST_CTX)
[req, client, TEST_CTX](ReqResult result, const HttpResponsePtr &resp) {
REQUIRE(result == ReqResult::Ok);

/// Get cookie
auto &id = resp->getCookie("JSESSIONID");
REQUIRE(id);

sessionID = id;
client->addCookie(id);

auto req1 = HttpRequest::newHttpRequest();
req1->setMethod(drogon::Get);
req1->setPath("/slow");
Expand Down
12 changes: 8 additions & 4 deletions lib/tests/integration_test/server/TimeFilter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,14 @@ void TimeFilter::doFilter(const HttpRequestPtr &req,
trantor::Date now = trantor::Date::date();
if (!req->session())
{
// no session support by framework,pls enable session
auto resp = HttpResponse::newNotFoundResponse();
cb(resp);
return;
bool is_session_set = req->setSession();
if (!is_session_set)
{
// no session support by framework,pls enable session
auto resp = HttpResponse::newNotFoundResponse();
cb(resp);
return;
}
}
auto lastDate = req->session()->getOptional<trantor::Date>(VDate);
if (lastDate)
Expand Down
1 change: 1 addition & 0 deletions lib/tests/integration_test/server/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ int main()

app().setDocumentRoot("./");
app().enableSession(60);
app().enableSaveAnonSession();

std::map<std::string, std::string> config_credentials;
std::string realm("drogonRealm");
Expand Down

0 comments on commit 6ed18d3

Please sign in to comment.