rcpp_framework/core/session.h

198 lines
4.6 KiB
C++

/**
*
* Session.h
* An Tao
*
* Copyright 2018, An Tao. All rights reserved.
* https://github.com/an-tao/drogon
* Use of this source code is governed by a MIT license
* that can be found in the License file.
*
* Drogon
*
*/
#pragma once
#include <core/any.h>
#include <trantor/utils/Logger.h>
#include <map>
#include <memory>
#include <mutex>
#include <thread>
namespace drogon
{
/**
* @brief This class represents a session stored in the framework.
* One can get or set any type of data to a session object.
*/
class Session
{
public:
/**
* @brief Get the data identified by the key parameter.
* @note if the data is not found, a default value is returned.
* For example:
* @code
auto &userName = sessionPtr->get<std::string>("user name");
@endcode
*/
template <typename T>
const T &get(const std::string &key) const
{
const static T nullVal = T();
std::lock_guard<std::mutex> lck(mutex_);
auto it = sessionMap_.find(key);
if (it != sessionMap_.end())
{
if (typeid(T) == it->second.type())
{
return *(any_cast<T>(&(it->second)));
}
else
{
LOG_ERROR << "Bad type";
}
}
return nullVal;
}
/**
* @brief Get the 'any' object identified by the given key
*/
any &operator[](const std::string &key)
{
std::lock_guard<std::mutex> lck(mutex_);
return sessionMap_[key];
}
/**
* @brief Insert a key-value pair
* @note here the any object can be created implicitly. for example
* @code
sessionPtr->insert("user name", userNameString);
@endcode
*/
void insert(const std::string &key, const any &obj)
{
std::lock_guard<std::mutex> lck(mutex_);
sessionMap_[key] = obj;
}
/**
* @brief Insert a key-value pair
* @note here the any object can be created implicitly. for example
* @code
sessionPtr->insert("user name", userNameString);
@endcode
*/
void insert(const std::string &key, any &&obj)
{
std::lock_guard<std::mutex> lck(mutex_);
sessionMap_[key] = std::move(obj);
}
/**
* @brief Erase the data identified by the given key.
*/
void erase(const std::string &key)
{
std::lock_guard<std::mutex> lck(mutex_);
sessionMap_.erase(key);
}
/**
* @brief Retrun true if the data identified by the key exists.
*/
bool find(const std::string &key)
{
std::lock_guard<std::mutex> lck(mutex_);
if (sessionMap_.find(key) == sessionMap_.end())
{
return false;
}
return true;
}
/**
* @brief Clear all data in the session.
*/
void clear()
{
std::lock_guard<std::mutex> lck(mutex_);
sessionMap_.clear();
}
/**
* @brief Get the session ID of the current session.
*/
std::string sessionId() const
{
std::lock_guard<std::mutex> lck(mutex_);
return sessionId_;
}
/**
* @brief Let the framework create a new session ID for this session and set
* it to the client.
* @note This method does not change the session ID now.
*/
void changeSessionIdToClient()
{
needToChange_ = true;
needToSet_ = true;
}
Session() = delete;
private:
using SessionMap = std::map<std::string, any>;
SessionMap sessionMap_;
mutable std::mutex mutex_;
std::string sessionId_;
bool needToSet_{false};
bool needToChange_{false};
friend class SessionManager;
friend class HttpAppFrameworkImpl;
/**
* @brief Constructor, usually called by the framework
*/
Session(const std::string &id, bool needToSet)
: sessionId_(id), needToSet_(needToSet)
{
}
/**
* @brief Change the state of the session, usually called by the framework
*/
void hasSet()
{
needToSet_ = false;
}
/**
* @brief If the session ID needs to be changed.
*
*/
bool needToChangeSessionId() const
{
return needToChange_;
}
/**
* @brief If the session ID needs to be set to the client through cookie,
* return true
*/
bool needSetToClient() const
{
return needToSet_;
}
void setSessionId(const std::string &id)
{
std::lock_guard<std::mutex> lck(mutex_);
sessionId_ = id;
needToChange_ = false;
}
};
using SessionPtr = std::shared_ptr<Session>;
} // namespace drogon