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

/libs/cgi/example/fcgi/echo/main.cpp

http://github.com/darrengarvey/cgi
C++ | 208 lines | 119 code | 23 blank | 66 comment | 4 complexity | d80f7838b74b95245daed283a29d349d MD5 | raw file
  1. // -- echo/main.hpp --
  2. //
  3. // Copyright (c) Darren Garvey 2007-2009.
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. ////////////////////////////////////////////////////////////////
  9. //
  10. //[fcgi_echo
  11. //
  12. // This example simply echoes all variables back to the user. ie.
  13. // the environment and the parsed GET, POST and cookie variables.
  14. // Note that GET and cookie variables come from the environment
  15. // variables QUERY_STRING and HTTP_COOKIE respectively.
  16. //
  17. ///////////////////////////////////////////////////////////
  18. #include <iostream>
  19. ///////////////////////////////////////////////////////////
  20. #include <boost/date_time/posix_time/posix_time.hpp>
  21. #include <boost/program_options/environment_iterator.hpp>
  22. ///////////////////////////////////////////////////////////
  23. #include "boost/cgi/fcgi.hpp"
  24. //using namespace std;
  25. using std::cerr;
  26. using std::endl;
  27. namespace fcgi = boost::fcgi;
  28. // The styling information for the page, just to make things look clearer.
  29. static const char* gCSS_text =
  30. "body { padding: 0; margin: 3%; border-color: #efe; }"
  31. "ul.data-map .title"
  32. "{ font-weight: bold; font-size: large; }"
  33. "ul.data-map"
  34. "{ border: 1px dotted; padding: 2px 3px 2px 3px; margin-bottom: 3%; }"
  35. "ul.data-map li"
  36. "{ border-top: 1px dotted; overflow: auto; padding: 0; margin: 0; }"
  37. "ul.data-map div.name"
  38. "{ position: relative; float: left; width: 30%; font-weight: bold; }"
  39. "ul.data-map div.value"
  40. "{ position: relative; float: left; width: 65%; left: 1%;"
  41. " border-left: 1px solid; padding: 0 5px 0 5px;"
  42. " overflow: auto; white-space: pre; }"
  43. ".clear"
  44. "{ clear: both; }"
  45. ;
  46. std::size_t process_id()
  47. {
  48. #if defined(BOOST_WINDOWS)
  49. return _getpid();
  50. #else
  51. return getpid();
  52. #endif
  53. }
  54. template<typename OStream, typename Request, typename Map>
  55. void format_map(OStream& os, Request& req, Map& m, const std::string& title);
  56. int handle_request(fcgi::request& req);
  57. int main()
  58. {
  59. try {
  60. // Make a `service` (more about this in other examples).
  61. fcgi::service s;
  62. // Make an `acceptor` for accepting requests through.
  63. fcgi::acceptor a(s);
  64. //
  65. // An acceptor can take a request handler as an argument to `accept` and it
  66. // will accept a request and pass the handler the request. The return value
  67. // of `accept` when used like this is the result of the handler.
  68. //
  69. // Note that a request handler is any function or function object with the
  70. // signature:
  71. // boost::function<int (boost::fcgi::request&)>
  72. // See the documentation for Boost.Function and Boost.Bind for more.
  73. //
  74. // The acceptor maintains an internal queue of requests and will reuse a
  75. // dead request if one is waiting.
  76. //
  77. // After the initial setup, we can enter a loop to handle one request at a
  78. // time until there's an error of some sort.
  79. //
  80. int status(0);
  81. do {
  82. status = a.accept(&handle_request);
  83. } while (!status);
  84. return status;
  85. }catch(boost::system::system_error const& se){
  86. // This is the type of exception thrown by the library.
  87. std::cerr<< "[fcgi] System error: " << se.what() << std::endl;
  88. return -1;
  89. }catch(std::exception const& e){
  90. // Catch any other exceptions
  91. std::cerr<< "[fcgi] Exception: " << e.what() << std::endl;
  92. return -2;
  93. }catch(...){
  94. std::cerr<< "[fcgi] Uncaught exception!" << std::endl;
  95. return -3;
  96. }
  97. }
  98. /// Handle one request.
  99. int handle_request(fcgi::request& req)
  100. {
  101. boost::system::error_code ec;
  102. //
  103. // Load in the request data so we can access it easily.
  104. //
  105. req.load(fcgi::parse_all);
  106. //
  107. // Construct a `response` object (makes writing/sending responses easier).
  108. //
  109. fcgi::response resp;
  110. //
  111. // Responses in CGI programs require at least a 'Content-type' header. The
  112. // library provides helpers for several common headers:
  113. //
  114. resp<< fcgi::content_type("text/html");
  115. // You can also stream text to a response.
  116. // All of this just prints out the form
  117. resp<< "<html>"
  118. "<head>"
  119. "<title>FastCGI Echo Example</title>"
  120. "<style type=\"text/css\">"
  121. << gCSS_text <<
  122. "</style>"
  123. "<head>"
  124. "<body>"
  125. "Request ID = " << req.id() << "<br />"
  126. "Process ID = " << process_id() << "<br />"
  127. "<form method=post enctype=\"multipart/form-data\">"
  128. "<input type=text name=name value='"
  129. << req.post.pick("name", "") << "' />"
  130. "<br />"
  131. "<input type=text name=hello value='"
  132. << req.post.pick("hello", "") << "' />"
  133. "<br />"
  134. "<input type=file name=user_file />"
  135. "<input type=hidden name=cmd value=multipart_test />"
  136. "<br />"
  137. "<input type=submit value=submit />"
  138. "</form><p />";
  139. // Show the request data in a formatted table.
  140. format_map(resp, req, req.env, "Environment Variables");
  141. format_map(resp, req, req.get, "GET Variables");
  142. format_map(resp, req, req.post, "POST Variables");
  143. format_map(resp, req, req.uploads, "File Uploads");
  144. format_map(resp, req, req.cookies, "Cookie Variables");
  145. // Print the buffer containing the POST data and the FastCGI params.
  146. resp<< "<pre>";
  147. resp<< std::string(req.post_buffer().begin(), req.post_buffer().end());
  148. resp<< "</pre>";
  149. //
  150. // Response headers can be added at any time before send/flushing it:
  151. //
  152. resp<< "Response content-length == "
  153. << resp.content_length(); // the content-length (returns std::size_t)
  154. // This function finishes up. The optional third argument
  155. // is the program status (default: 0).
  156. return fcgi::commit(req, resp);
  157. }
  158. //
  159. // This function writes the title and map contents to the ostream in an
  160. // HTML-encoded format (to make them easier on the eye).
  161. //
  162. template<typename OStream, typename Request, typename Map>
  163. void format_map(OStream& os, Request& req, Map& m, const std::string& title)
  164. {
  165. os<< "<ul class=\"data-map\">"
  166. "<div class=\"title\">"
  167. << title
  168. << "</div>";
  169. if (m.empty())
  170. os<< "<li>EMPTY</li>";
  171. else
  172. for (typename Map::const_iterator i = m.begin(); i != m.end(); ++i)
  173. {
  174. os<< "<li>"
  175. "<div class=\"name\">"
  176. << i->first
  177. << "</div>"
  178. "<div class=\"value\">"
  179. << i->second
  180. << "</div>"
  181. "</li>";
  182. }
  183. os<< "<div class=\"clear\"></div></ul>";
  184. }
  185. //]