会话(Session)是web应用的重要概念,用于在服务端保存客户端的状态,一般和浏览器的cookie配合,drogon提供了对会话的支持。drogon默认关闭会话选择,你也可以通过如下接口关闭或打开:

  1. void disableSession();
  2. void enableSession(const size_t timeout=0, Cookie::SameSite sameSite=Cooie::SameSite::kNull);

都是通过HttpAppFramework单例调用,timeout参数代表了会话失效的时间,单位是秒,框架默认值是1200,即如果用户20分钟以上没有访问应用,则他对应的会话就失效了。timeout设置为0表示drogon将在整个生存期保留用户的会话;

打开会话特性前请确定你的客户端支持cookie,否则,drogon会为每次不含SessionID的请求创建新的会话,这会白白浪费内存和计算资源。

会话对象

drogon的会话对象类型是drogon::Session,它和HttpViewData非常类似,可以通过关键字存取任意类型的对象;支持并发读写;具体的使用请参考Session class的说明;

drogon框架会把会话对象放到HttpRequest对象里传递给用户,用户可以通过HttpRequest类的如下接口获取Session对象。

  1. SessionPtr session() const;

获得的是Session对象的智能指针,通过它可以存取各种对象;

会话的例子

我们这次加一个需要会话支持的功能,比如,我们要限制用户的访问频度,某一次访问后,如果10秒以内再次访问,就返回错误,否则返回ok。我们需要在会话里记录上次访问的时间,然后和本次访问的时间做比较,就可以实现这个功能。

我们创建一个Filter来实现这个功能,假设类名是TimeFilter,实现如下:

  1. #include "TimeFilter.h"
  2. #include <trantor/utils/Date.h>
  3. #include <trantor/utils/Logger.h>
  4. #define VDate "visitDate"
  5. void TimeFilter::doFilter(const HttpRequestPtr &req,
  6. FilterCallback &&cb,
  7. FilterChainCallback &&ccb)
  8. {
  9. trantor::Date now=trantor::Date::date();
  10. LOG_TRACE<<"";
  11. if(req->session()->find(VDate))
  12. {
  13. auto lastDate=req->session()->get<trantor::Date>(VDate);
  14. LOG_TRACE<<"last:"<<lastDate.toFormattedString(false);
  15. req->session()->modify<trantor::Date>(VDate,
  16. [now](trantor::Date &vdate) {
  17. vdate = now;
  18. });
  19. LOG_TRACE<<"update visitDate";
  20. if(now>lastDate.after(10))
  21. {
  22. //10 sec later can visit again;
  23. ccb();
  24. return;
  25. }
  26. else
  27. {
  28. Json::Value json;
  29. json["result"]="error";
  30. json["message"]="Access interval should be at least 10 seconds";
  31. auto res=HttpResponse::newHttpJsonResponse(json);
  32. cb(res);
  33. return;
  34. }
  35. }
  36. LOG_TRACE<<"first access,insert visitDate";
  37. req->session()->insert(VDate,now);
  38. ccb();
  39. }

我们再注册一个lambda表达式到/slow路径上,同时附加上TimeFilter,代码如下:

  1. drogon::HttpAppFramework::instance()
  2. .registerHandler
  3. ("/slow",
  4. [=](const HttpRequestPtr &req,
  5. std::function<void (const HttpResponsePtr &)> &&callback)
  6. {
  7. Json::Value json;
  8. json["result"]="ok";
  9. auto resp=HttpResponse::newHttpJsonResponse(json);
  10. callback(resp);
  11. },
  12. {Get,"TimeFilter"}
  13. );

调用框架接口打开会话

  1. drogon::HttpAppFramework::instance().enableSession(1200);

用cmake重新编译整个工程,运行目标程序webapp,就可以通过浏览器看到效果了。

数据库