PageRenderTime 508ms CodeModel.GetById 91ms app.highlight 19ms RepoModel.GetById 293ms app.codeStats 40ms

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