PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/cgi/example/cgi/DebugServer2/TracebackServer.cpp

http://github.com/darrengarvey/cgi
C++ | 143 lines | 123 code | 18 blank | 2 comment | 9 complexity | 703466f520d8ef34b2a9c5222fac5dd2 MD5 | raw file
  1. #include "TracebackServer.hpp"
  2. #include <boost/chrono/chrono.hpp>
  3. #define TBS_TEMPLATE__DEBUG_VIEW "../stencils/debug_view.html"
  4. namespace detail {
  5. boost::uint64_t
  6. get_microseconds(boost::chrono::process_clock::duration const& tp)
  7. {
  8. return boost::chrono::duration_cast<boost::chrono::microseconds>(tp).count();
  9. }
  10. } // namespace detail
  11. TracebackServer::TracebackServer(void)
  12. : timer_()
  13. {
  14. }
  15. TracebackServer::~TracebackServer(void)
  16. {
  17. }
  18. template<typename MapT>
  19. void TracebackServer::expand_map(dictionary_type& dict, MapT& data, std::string const& title)
  20. {
  21. dictionary_type* sub_dict = dict.AddSectionDictionary("REQUEST_DATA_MAP");
  22. sub_dict->SetValue("REQUEST_DATA_MAP_TITLE", title);
  23. if (data.empty())
  24. sub_dict->ShowSection("REQUEST_DATA_MAP_EMPTY");
  25. else {
  26. for(typename MapT::const_iterator iter(data.begin()), end(data.end()); iter != end; ++iter)
  27. {
  28. dictionary_type* nvpair_dict = sub_dict->AddSectionDictionary("REQUEST_DATA_PAIR");
  29. nvpair_dict->SetValue("REQUEST_DATA_NAME", iter->first.c_str());
  30. nvpair_dict->SetValue("REQUEST_DATA_VALUE", iter->second.c_str());
  31. }
  32. }
  33. }
  34. void TracebackServer::stop_timer()
  35. {
  36. timer_.elapsed(stop_times_);
  37. }
  38. void TracebackServer::dump_times(dictionary_type& dict)
  39. {
  40. dict.SetValue("RUNNING_TIME_RESOLUTION", "microseconds");
  41. dict.SetFormattedValue("REAL_TIME", "%d us", detail::get_microseconds(stop_times_.real));
  42. dict.SetFormattedValue("CPU_TIME", "%d us", detail::get_microseconds(stop_times_.user + stop_times_.system));
  43. dict.SetFormattedValue("USER_TIME", "%d us", detail::get_microseconds(stop_times_.user));
  44. dict.SetFormattedValue("SYSTEM_TIME", "%d us", detail::get_microseconds(stop_times_.system));
  45. dict.ShowSection("RUNNING_TIME");
  46. }
  47. void TracebackServer::bomb_out(std::string const& error, response_type& response, request_type& request)
  48. {
  49. stop_timer();
  50. response_type resp2;
  51. template_ = ctemplate::Template::GetTemplate(TBS_TEMPLATE__DEBUG_VIEW, ctemplate::STRIP_WHITESPACE);
  52. dictionary_type dict("debug_view");
  53. dict.SetValue("ERROR", error);
  54. expand_map(dict, request.env, "Environment Data");
  55. expand_map(dict, request.form, "Form (" + request.method() + ") data");
  56. expand_map(dict, request.cookies, "Cookies");
  57. BOOST_FOREACH(std::string& hstring, response.headers())
  58. {
  59. dict.SetValueAndShowSection("HEADER", hstring, "RESPONSE_HEADER");
  60. }
  61. dump_times(dict);
  62. //dict.SetValue("ORIGINAL_RESPONSE", response.rdbuf()->data());
  63. std::string debug_output;
  64. template_->Expand(&debug_output, &dict);
  65. resp2<< boost::cgi::content_type("text/html")
  66. << debug_output
  67. << response;
  68. resp2.send(request.client());
  69. request.close();
  70. }
  71. void TracebackServer::bomb_out(boost::system::system_error* err, response_type& response, request_type& request) {
  72. //dictionary_type* sub_dict = dict.AddSectionDictionary("REQUEST_DATA_MAP");
  73. typedef request_type::string_type string;
  74. string err_msg("boost::system::system_error*<ul class=nvpair><li class=name>Code:</li>");
  75. err_msg += string("<li class=value>") + boost::lexical_cast<std::string>(err->code()) + "</li>"
  76. + "<li class=name>What:</li>"
  77. + "<li class=value>" + err->what() + "</li>"
  78. + "<li class=name>Type:</li>"
  79. + "<li class=value>" + typeid(*err).name() + "</li><br class=clear /></ul>";
  80. bomb_out(err_msg, response, request);
  81. }
  82. void TracebackServer::bomb_out(std::exception* e, response_type& response, request_type& request) {
  83. typedef request_type::string_type string;
  84. string err_msg("std::exception*<ul class=nvpair><li class=name>What:</li>");
  85. err_msg += string("<li class=value>") + e->what() + "</li>"
  86. + "<li class=name>Type:</li>"
  87. + "<li class=value>" + typeid(*e).name() + "</li><br class=clear /></ul>";
  88. bomb_out(err_msg, response, request);
  89. }
  90. void TracebackServer::bomb_out(std::exception& e, response_type& response, request_type& request) {
  91. typedef request_type::string_type string;
  92. string err_msg("std::exception<ul class=nvpair><li class=name>What:</li>");
  93. err_msg += string("<li class=value>") + e.what() + "</li>"
  94. + "<li class=name>Type:</li>"
  95. + "<li class=value>" + typeid(e).name() + "</li><br class=clear /></ul>";
  96. bomb_out(err_msg, response, request);
  97. }
  98. bool TracebackServer::run(callback_type const& callback)
  99. {
  100. timer_.start();
  101. request_type request;
  102. response_type response;
  103. try {
  104. request.load(boost::cgi::parse_all);
  105. int ret(callback(request, response));
  106. if (request.form["debug"] == "1") {
  107. bomb_out("** Debug mode ** - client callback returned code #" + boost::lexical_cast<std::string>(ret)
  108. , response, request);
  109. }else
  110. if (!ret) {
  111. return 0 == boost::cgi::commit(request, response);
  112. } else {
  113. bomb_out("Callback returned code #" + boost::lexical_cast<std::string>(ret) + "; unknown error", response, request);
  114. }
  115. }catch(boost::system::system_error* err) {
  116. bomb_out(err, response, request); return false;
  117. }catch(std::exception* e) {
  118. bomb_out(e, response, request); return false;
  119. }catch(std::exception& e) {
  120. bomb_out(e, response, request); return false;
  121. }catch(...){
  122. bomb_out("Unknown exception (captor: CGI hello example TracebackServer::run())", response, request); return false;
  123. }
  124. return false;
  125. }