PageRenderTime 35ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/cgi/example/cgi/DebugServer/TracingServer.cpp

http://github.com/darrengarvey/cgi
C++ | 250 lines | 225 code | 16 blank | 9 comment | 7 complexity | f3069624a7f8a69abd01fce7c15bb0ad MD5 | raw file
  1. #include "TracingServer.hpp"
  2. #include <boost/chrono/chrono.hpp>
  3. #include <typeinfo>
  4. namespace detail {
  5. // The styling information for the page.
  6. static const char* gCSS_text =
  7. //"body { padding: 0; margin: 3%; border-color: #efe; }"
  8. ".info"
  9. "{"
  10. "border-color: #ca3766;"
  11. "border-width: 1px 0 1px 0;"
  12. "border-style: solid;"
  13. "padding: 2px 8px 2px 8px;"
  14. "margin: 1em"
  15. "}"
  16. "#response"
  17. "{"
  18. "text-align: center;"
  19. "padding: 20px 30px 20px 30px;"
  20. "margin: 1em;"
  21. "border-width: 2px 0 2px 0;"
  22. "border-style: solid;"
  23. "border-color: #ca3766;"
  24. "}"
  25. ".var_map_title"
  26. "{"
  27. "font-weight: bold;"
  28. "font-size: large;"
  29. "}"
  30. ".var_map"
  31. "{"
  32. "border: 1px dotted;"
  33. "padding: 2px 3px 2px 3px;"
  34. "margin: 15px 0 15px 0;"
  35. "}"
  36. ".var_pair"
  37. "{"
  38. "border-top: 1px dotted;"
  39. "overflow: auto;"
  40. "padding: 0;"
  41. "margin: 0;"
  42. "}"
  43. ".var_name"
  44. "{"
  45. "position: relative;"
  46. "float: left;"
  47. "width: 30%;"
  48. "font-weight: bold;"
  49. "}"
  50. ".var_value"
  51. "{"
  52. "position: relative;"
  53. "float: left;"
  54. "width: 65%;"
  55. "left: 1%;"
  56. "border-left: 1px solid;"
  57. "padding: 0 5px 0 5px;"
  58. "overflow: auto;"
  59. "white-space: pre;"
  60. "}"
  61. "ul.nvpair"
  62. "{"
  63. "list-style-type: none;"
  64. "padding: 0;"
  65. "margin: 0;"
  66. "}"
  67. "ul.nvpair li"
  68. "{"
  69. "display: inline;"
  70. "width: 175px;"
  71. "float: left;"
  72. "}"
  73. "ul.nvpair li.name"
  74. "{"
  75. "text-align: right;"
  76. "padding-right: 1em;"
  77. "clear: left;"
  78. "}"
  79. "ul.nvpair li.value"
  80. "{"
  81. "text-align: left;"
  82. "padding-left: 1em;"
  83. "}"
  84. ".clear { clear: both; }"
  85. ;
  86. //
  87. // This function writes the title and map contents to the ostream in an
  88. // HTML-encoded format (to make them easier on the eye).
  89. //
  90. template<typename OStreamT, typename MapT>
  91. void format_map(OStreamT& os, MapT& m, const std::string& title)
  92. {
  93. os<< "<div class=\"var_map\">"
  94. "<div class=\"var_map_title\">"
  95. << title
  96. << "</div><ul>";
  97. if (m.empty())
  98. os<< "<ul class=\"var_pair\">EMPTY</ul>";
  99. else
  100. for (typename MapT::const_iterator i = m.begin(); i != m.end(); ++i)
  101. {
  102. os<< "<li class=\"var_pair\">"
  103. "<div class=\"var_name\">"
  104. << i->first
  105. << "</div>"
  106. "<div class=\"var_value\">"
  107. << i->second
  108. << "</div>"
  109. "</li>";
  110. }
  111. os<< "</ul></div>";
  112. }
  113. boost::uint64_t
  114. get_microseconds(boost::chrono::process_clock::duration& tp)
  115. {
  116. return boost::chrono::duration_cast<boost::chrono::microseconds>(tp).count();
  117. }
  118. }
  119. TracingServer::TracingServer(void)
  120. : timer_()
  121. {
  122. }
  123. TracingServer::~TracingServer(void)
  124. {
  125. }
  126. void TracingServer::bomb_out(std::string const& error, response_type& response, request_type& request)
  127. {
  128. boost::chrono::process_times times;
  129. timer_.elapsed(times);
  130. response_type resp2;
  131. resp2<< boost::cgi::content_type("text/html")
  132. << "<html>"
  133. "<head>"
  134. "<title>CGI Echo Example</title>"
  135. "<style type=\"text/css\">"
  136. << detail::gCSS_text <<
  137. "</style>"
  138. "<head>"
  139. "<body>"
  140. "<p style='font-weight: bold'>"
  141. "<h1 style='font-size: x-large'>Problem found.</h1>"
  142. "<p>The original response follows, after some details about the error that occurred and the request that caused it</p>"
  143. "<p>First, the error that we tried to detect:</p>"
  144. "</p>"
  145. "<div class=\"info\">"
  146. << error
  147. << "</div>"
  148. "The request took the following time to process:"
  149. "<div class=\"info\">"
  150. "<ul class='nvpair'>"
  151. "<li class='name'>Real time</li>"
  152. "<li class='value'>" << detail::get_microseconds(times.real) << " microseconds</li>"
  153. "<li class='name'>User time</li>"
  154. "<li class='value'>" << detail::get_microseconds(times.user) << " microseconds</li>"
  155. "<li class='name'>System time</li>"
  156. "<li class='value'>" << detail::get_microseconds(times.system) << " microseconds</li>"
  157. "</ul>"
  158. "<br class='clear' />"
  159. "</div>"
  160. "Some details about the request:"
  161. "<div class=\"info\">";
  162. //style='"
  163. // "border-color: #ca3766;" "border-width: 1px 0 1px 0;" "border-style: solid;"
  164. // "padding: 2px 8px 2px 8px;" "margin: 1em" "'>";
  165. detail::format_map(resp2, request.env, "Environment data");
  166. detail::format_map(resp2, request.form, "Form [" + request.request_method() + "] Variables");
  167. detail::format_map(resp2, request.cookies, "Cookies");
  168. resp2<< "</div>"
  169. "<p>The headers sent in the original (broken) response were:</p>"
  170. "<div class=\"info\">"
  171. "<pre style='white-space:pre; padding-left: 3em; margin-left: 1em'>"
  172. "<ul>";
  173. BOOST_FOREACH(std::string& hstring, response.headers())
  174. {
  175. resp2<< "<li>" << hstring << "</li>";
  176. }
  177. resp2<< "</ul>"
  178. << "</pre>"
  179. "</div>"
  180. "Below is the original response (inside borders, with (x=30;y=20)px of padding):"
  181. "<div id='response'>"
  182. << response // print out the original response
  183. << "</div>"
  184. "</body>"
  185. "</html>";
  186. resp2.send(request.client());
  187. request.close();
  188. }
  189. void TracingServer::bomb_out(boost::system::system_error* err, response_type& response, request_type& request) {
  190. typedef request_type::string_type string;
  191. string err_msg("<ul class=nvpair>boost::system::system_error*<li class=name>Code:</li>");
  192. err_msg += string("<li class=value>") + boost::lexical_cast<std::string>(err->code()) + "</li>"
  193. + "<li class=name>What:</li>"
  194. + "<li class=value>" + err->what() + "</li>"
  195. + "<li class=name>Type:</li>"
  196. + "<li class=value>" + typeid(err).name() + "</li><br class=clear /></ul>";
  197. bomb_out(err_msg, response, request);
  198. }
  199. void TracingServer::bomb_out(std::exception& e, response_type& response, request_type& request) {
  200. typedef request_type::string_type string;
  201. string err_msg("<ul class=nvpair>std::exception<li class=name>What:</li>");
  202. err_msg += string("<li class=value>") + e.what() + "</li>"
  203. + "<li class=name>Type:</li>"
  204. + "<li class=value>" + typeid(e).name() + "</li><br class=clear /></ul>";
  205. bomb_out(err_msg, response, request);
  206. }
  207. bool TracingServer::run(callback_type const& callback)
  208. {
  209. timer_.start();
  210. request_type request;
  211. response_type response;
  212. try {
  213. request.load(boost::cgi::parse_all);
  214. int ret(callback(request, response));
  215. if (request.form["debug"] == "1") {
  216. bomb_out("** Debug mode ** - client callback returned code #" + boost::lexical_cast<std::string>(ret)
  217. , response, request);
  218. }else
  219. if (!ret) {
  220. response.send(request.client());
  221. request.close();
  222. return true;
  223. } else {
  224. bomb_out("Callback returned code #" + boost::lexical_cast<std::string>(ret) + "; unknown error", response, request);
  225. }
  226. }catch(boost::system::system_error* err) {
  227. bomb_out(err, response, request); return false;
  228. }catch(std::exception& e) {
  229. bomb_out(e, response, request); return false;
  230. }catch(...){
  231. bomb_out("Unknown error (captor: CGI hello example TracingServer::run())", response, request); return false;
  232. }
  233. return false;
  234. }