PageRenderTime 54ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

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

http://github.com/darrengarvey/cgi
C++ | 226 lines | 125 code | 22 blank | 79 comment | 5 complexity | 01bf52a0f9488852813daeabdab2dde7 MD5 | raw file
  1. // -- main.hpp --
  2. //
  3. // Copyright (c) Darren Garvey 2007.
  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_threaded
  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 <boost/thread.hpp>
  19. #include <boost/date_time/posix_time/posix_time.hpp>
  20. #include <boost/program_options/environment_iterator.hpp>
  21. ///////////////////////////////////////////////////////////
  22. #include "boost/cgi/fcgi.hpp"
  23. #include "boost/cgi/common/commit.hpp"
  24. //using namespace std;
  25. using namespace boost::fcgi;
  26. // The styling information for the page, just to make things look nicer.
  27. static const char* gCSS_text =
  28. "body { padding: 0; margin: 3%; border-color: #efe; }"
  29. ".var_map_title"
  30. "{ font-weight: bold; font-size: large; }"
  31. ".var_map"
  32. "{ border: 1px dotted; padding: 2px 3px 2px 3px; margin-bottom: 3%; }"
  33. ".var_pair"
  34. "{ border-top: 1px dotted; overflow: auto; padding: 0; margin: 0; }"
  35. ".var_name"
  36. "{ position: relative; float: left; width: 30%; font-weight: bold; }"
  37. ".var_value"
  38. "{ position: relative; float: left; width: 65%; left: 1%;"
  39. " border-left: 1px solid; padding: 0 5px 0 5px;"
  40. " overflow: auto; white-space: pre; }"
  41. ;
  42. //
  43. // This function writes the title and map contents to the ostream in an
  44. // HTML-encoded format (to make them easier on the eye).
  45. //
  46. template<typename OStreamT, typename MapT>
  47. void format_map(OStreamT& os, MapT& m, const std::string& title)
  48. {
  49. os<< "<ul class=\"var_map\">"
  50. "<div class=\"var_map_title\">"
  51. << title
  52. << "</div>";
  53. if (m.empty())
  54. os<< "<li class=\"var_pair\">EMPTY</li>";
  55. else
  56. for (typename MapT::const_iterator i = m.begin(); i != m.end(); ++i)
  57. {
  58. os<< "<li class=\"var_pair\">"
  59. "<div class=\"var_name\">"
  60. << i->first
  61. << "</div>"
  62. "<div class=\"var_value\">"
  63. << i->second
  64. << "</div>"
  65. "</li>";
  66. }
  67. os<< "</ul>";
  68. }
  69. std::size_t process_id()
  70. {
  71. #if defined(BOOST_WINDOWS)
  72. return _getpid();
  73. #else
  74. return getpid();
  75. #endif
  76. }
  77. /// This function accepts and handles a single request.
  78. template<typename Acceptor, typename Request>
  79. int handle_request(Acceptor& a, Request& req)
  80. {
  81. //
  82. // Load in the request data so we can access it easily.
  83. //
  84. req.load(parse_all); // Read and parse STDIN (ie. POST) data.
  85. //
  86. // Construct a `response` object (makes writing/sending responses easier).
  87. //
  88. response resp;
  89. //
  90. // Responses in CGI programs require at least a 'Content-type' header. The
  91. // library provides helpers for several common headers:
  92. //
  93. resp<< content_type("text/html");
  94. // You can also stream text to a response.
  95. // All of this just prints out the form
  96. resp<< "<html>"
  97. "<head>"
  98. "<title>FastCGI Echo Example</title>"
  99. "<style type=\"text/css\">"
  100. << gCSS_text <<
  101. "</style>"
  102. "<head>"
  103. "<body>"
  104. "Request ID = " << req.id() << "<br />"
  105. "Process ID = " << process_id() << "<br />"
  106. "<form method=post>" // enctype=\"multipart/form-data\">"
  107. "<input type=text name=name value='"
  108. << req.post["name"] << "' />"
  109. "<br />"
  110. "<input type=text name=hello value='"
  111. << req.post["hello"] << "' />"
  112. "<br />"
  113. "<input type=file name=user_file />"
  114. "<input type=hidden name=cmd value=multipart_test />"
  115. "<br />"
  116. "<input type=submit value=submit />"
  117. "</form><p />";
  118. //
  119. // Use the function defined above to show some of the request data.
  120. // (this function isn't part of the library)
  121. //
  122. format_map(resp, req.env, "Environment Variables");
  123. format_map(resp, req.form, req.request_method() + " Variables");
  124. format_map(resp, req.cookies, "Cookie Variables");
  125. // Print the complete buffer containing the POST data and the FastCGI params.
  126. resp<< "<pre>";
  127. BOOST_FOREACH(char& ch, req.post_buffer())
  128. {
  129. resp<< ch;
  130. }
  131. // << req.get_buffer()
  132. resp<< "</pre>";
  133. //
  134. // Response headers can be added at any time before send/flushing it:
  135. //
  136. resp<< "Response content-length == "
  137. << resp.content_length() // the content-length (returns std::size_t)
  138. ;//<< content_length(resp); // a content-length header
  139. // This function finishes up:
  140. int ret = commit(req, resp, 0);
  141. //a.async_accept(req, boost::bind(&handle_request, boost::ref(a), boost::ref(req), _1));
  142. a.async_accept(boost::bind(
  143. &handle_request<boost::fcgi::acceptor, boost::fcgi::request>
  144. , boost::ref(a)
  145. , _1));
  146. return ret;
  147. //a->async_accept(req, boost::bind(&handle_request<boost::fcgi::acceptor*,boost::fcgi::request&>, a, _1));
  148. //a.async_accept(boost::bind(&handle_request<acceptor,request>, boost::ref(a), boost::ref(req)));
  149. //
  150. // It is equivalent to the below, where the third argument is represented by
  151. // `program_status`:
  152. //
  153. // resp.send(req.client());
  154. // req.close(resp.status(), program_status);
  155. // return program_status;
  156. //
  157. // Note: in this case `program_status == 0`.
  158. //
  159. }
  160. int main()
  161. {
  162. try {
  163. // Make a `service` (more about this in other examples).
  164. service s;
  165. // Make an `acceptor` for accepting requests through.
  166. acceptor a(s);
  167. //
  168. // After the initial setup, we can enter a loop to handle several requests
  169. // at a time until there's an error of some sort.
  170. //
  171. // Handle 50 requests at a time.
  172. for (int i(0); i < 2; ++i)
  173. {
  174. //
  175. // Now we asychronously accept a request. This will return immediately.
  176. //
  177. // The second argument is the handler that is called when a request is
  178. // accepted.
  179. //
  180. a.async_accept(boost::bind(
  181. &handle_request<boost::fcgi::acceptor, boost::fcgi::request>
  182. , boost::ref(a)
  183. , _1));
  184. }
  185. boost::thread_group threads;
  186. for (int i(50); i; --i) {
  187. threads.create_thread(boost::bind(&service::run, boost::ref(s)));
  188. }
  189. threads.join_all();
  190. return 0;
  191. }catch(boost::system::system_error const& se){
  192. // This is the type of error thrown by the library.
  193. //cerr<< "[fcgi] System error: " << se.what() << endl;
  194. return 1313;
  195. }catch(std::exception const& e){
  196. // Catch any other exceptions
  197. //cerr<< "[fcgi] Exception: " << e.what() << endl;
  198. return 666;
  199. }catch(...){
  200. //cerr<< "[fcgi] Uncaught exception!" << endl;
  201. return 667;
  202. }
  203. }
  204. //]