ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

398 lines
11 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
  4. //
  5. // See accompanying file COPYING.TXT file for licensing details.
  6. //
  7. ///////////////////////////////////////////////////////////////////////////////
  8. #ifndef CPPCMS_HTTP_RESPONSE_H
  9. #define CPPCMS_HTTP_RESPONSE_H
  10. #include <cppcms/defs.h>
  11. #include <booster/noncopyable.h>
  12. #include <booster/hold_ptr.h>
  13. #include <string>
  14. #include <iostream>
  15. #include <cppcms/cstdint.h>
  16. namespace booster{
  17. namespace system {
  18. class error_code;
  19. }
  20. }
  21. namespace cppcms {
  22. class cache_interface;
  23. namespace impl { namespace cgi { class connection; }}
  24. namespace http {
  25. class context;
  26. class cookie;
  27. ///
  28. /// \brief this class represents all HTTP/CGI response related API, generation of output content and
  29. /// HTTP headers.
  30. ///
  31. class CPPCMS_API response : public booster::noncopyable {
  32. public:
  33. ///
  34. /// This type represent the enum of HTTP Status type as of RFC 2616 sec. 6.1.1
  35. ///
  36. typedef enum {
  37. continue_transfer = 100,
  38. switching_protocol = 101,
  39. ok = 200,
  40. created = 201,
  41. accepted = 202,
  42. non_authoritative_information = 203,
  43. no_content = 204,
  44. reset_content = 205,
  45. partial_content = 206,
  46. multiple_choices = 300,
  47. moved_permanently = 301,
  48. found = 302,
  49. see_other = 303,
  50. not_modified = 304,
  51. use_proxy = 305,
  52. temporary_redirect = 307,
  53. bad_request = 400,
  54. unauthorized = 401,
  55. payment_required = 402,
  56. forbidden = 403,
  57. not_found = 404,
  58. method_not_allowed = 405,
  59. not_acceptable = 406,
  60. proxy_authentication_required = 407,
  61. request_time_out = 408,
  62. conflict = 409,
  63. gone = 410,
  64. precondition_failed = 412,
  65. request_entity_too_large = 413,
  66. request_uri_too_large = 414,
  67. unsupported_media_type = 415,
  68. requested_range_not_satisfiable = 416,
  69. expectation_failed = 417,
  70. internal_server_error = 500,
  71. not_implemented = 501,
  72. bad_gateway = 502,
  73. service_unavailable = 503,
  74. gateway_timeout = 504,
  75. http_version_not_supported = 505
  76. } status_type;
  77. ///
  78. /// This enum represents different types of IO modes giving fine grained control over HTTP output.
  79. ///
  80. /// These modes are set via io_mode member function
  81. ///
  82. typedef enum {
  83. normal, ///< Synchronous IO. Write the request, it is buffered and possible compressed using gzip.
  84. nogzip, ///< Same as normal but disable gzip compression
  85. raw, ///< User has full control over the output, it is also fully responsible for generation
  86. ///< of HTTP headers, no-session management given.
  87. asynchronous,
  88. ///< In this mode the data is buffered and never transferred unless it is requested by async_flush_output,
  89. ///< or async_complete_response member functions of http::context explicitly.
  90. asynchronous_raw
  91. ///< Same as asynchronous but the user is responsible for generation of its own HTTP headers.
  92. } io_mode_type;
  93. // Standard HTTP Response Headers RFC 2616
  94. ///
  95. /// Set HTTP Header Accept-Ranges
  96. ///
  97. void accept_ranges(std::string const &);
  98. ///
  99. /// Set HTTP Header Age
  100. ///
  101. void age(unsigned seconds);
  102. ///
  103. /// Set HTTP Header Allow
  104. ///
  105. void allow(std::string const &);
  106. ///
  107. /// Set HTTP Header Cache-Control
  108. ///
  109. void cache_control(std::string const &);
  110. ///
  111. /// Set HTTP Header Content-Encoding.
  112. ///
  113. /// Note: if you set this header manually, gzip compression will be automatically disabled.
  114. ///
  115. void content_encoding(std::string const &);
  116. ///
  117. /// Set HTTP Header Content-Language
  118. ///
  119. void content_language(std::string const &);
  120. ///
  121. /// Set HTTP Header Content-Length
  122. ///
  123. void content_length(unsigned long long len);
  124. ///
  125. /// Set HTTP Header Content-Location
  126. ///
  127. void content_location(std::string const &);
  128. ///
  129. /// Set HTTP Header Content-Md5
  130. ///
  131. void content_md5(std::string const &);
  132. ///
  133. /// Set HTTP Header Content-Range
  134. ///
  135. void content_range(std::string const &);
  136. ///
  137. /// Set HTTP Header Content-Type
  138. ///
  139. void content_type(std::string const &);
  140. ///
  141. /// Set HTTP Header Date
  142. ///
  143. void date(time_t);
  144. ///
  145. /// Set HTTP Header Etag
  146. ///
  147. void etag(std::string const &);
  148. ///
  149. /// Set HTTP Header Expires, it is formatted as HTTP Date-Time from the POSIX time \a t
  150. ///
  151. void expires(time_t t);
  152. ///
  153. /// Set HTTP Header Last-Modified, it is formatted as HTTP Date-Time from the POSIX time \a t
  154. ///
  155. void last_modified(time_t t);
  156. ///
  157. /// Set HTTP Header Location
  158. ///
  159. void location(std::string const &);
  160. ///
  161. /// Set HTTP Header Pragma
  162. ///
  163. void pragma(std::string const &);
  164. ///
  165. /// Set HTTP Header Proxy-Authenticate
  166. ///
  167. void proxy_authenticate(std::string const &);
  168. ///
  169. /// Set HTTP Header Retry-After
  170. ///
  171. void retry_after(std::string const &);
  172. ///
  173. /// Set HTTP Header Retry-After
  174. ///
  175. void retry_after(unsigned);
  176. ///
  177. /// Set GCI Status Header, the message is created according to the code automatically
  178. ///
  179. void status(int code);
  180. ///
  181. /// Set HTTP Header Status with the status code \a code and a custom \a message
  182. ///
  183. void status(int code,std::string const &message);
  184. ///
  185. /// Set HTTP Header Trailer
  186. ///
  187. void trailer(std::string const &);
  188. ///
  189. /// Set HTTP Header Transfer-Encoding, note
  190. ///
  191. void transfer_encoding(std::string const &);
  192. ///
  193. /// Set HTTP Header Vary
  194. ///
  195. void vary(std::string const &);
  196. ///
  197. /// Set HTTP Header Via
  198. ///
  199. void via(std::string const &);
  200. ///
  201. /// Set HTTP Header Warning
  202. ///
  203. void warning(std::string const &);
  204. ///
  205. /// Set HTTP Header WWW-Authenticate
  206. ///
  207. void www_authenticate(std::string const &);
  208. ///
  209. /// Set Generic HTTP header "name: value"
  210. ///
  211. void set_header(std::string const &name,std::string const &value);
  212. ///
  213. /// Get output header value, returns empty string if it is not set
  214. ///
  215. std::string get_header(std::string const &name);
  216. ///
  217. /// Erase specific header \a h
  218. ///
  219. void erase_header(std::string const &h);
  220. ///
  221. /// add header - independently of set_header/get_header/erase_header - allows
  222. /// to specify multiple headers of same type like Set-Cookie or WWW-Authenticate
  223. ///
  224. /// \ver{v1_2}
  225. void add_header(std::string const &name,std::string const &value);
  226. ///
  227. /// This function set HTTP Content-Type header, but unlike contet_type function it also adds
  228. /// current locale charset encoding (unless localization.disable_charset_in_content_type set to true in configuration)
  229. ///
  230. void set_content_header(std::string const &content_type);
  231. ///
  232. /// Shortcut to set_content_header("text/html") - this is the default content-type header
  233. ///
  234. void set_html_header();
  235. ///
  236. /// Shortcut to set_content_header("text/xhtml")
  237. ///
  238. void set_xhtml_header();
  239. ///
  240. /// Shortcut to set_content_header("text/plain")
  241. ///
  242. void set_plain_text_header();
  243. ///
  244. /// Redirect to other \a location by setting HTTP Location header and a Status header with a status \a status
  245. ///
  246. void set_redirect_header(std::string const &location,int status = found);
  247. ///
  248. /// Set HTTP Cookie
  249. ///
  250. void set_cookie(cookie const &);
  251. ///
  252. /// This creates a default HTTP response (including HTML body) with a status \a stat a message \a msg.
  253. ///
  254. /// Note: if \a msg is empty default message for HTTP Status code \a stat is used.
  255. ///
  256. void make_error_response(int stat,std::string const &msg = std::string());
  257. ///
  258. /// Get current io_mode, see a description for io_mode_type.
  259. ///
  260. io_mode_type io_mode();
  261. ///
  262. /// Set current io_mode, see a description for io_mode_type.
  263. ///
  264. /// Note: you can't change it after requesting for output stream, i.e. calling out() member function.
  265. ///
  266. void io_mode(io_mode_type);
  267. ///
  268. /// Request an output stream to write the body of HTTP response after writing headers.
  269. ///
  270. /// Note:
  271. ///
  272. /// - it triggers saving changes in the session, so further changes will have no effect.
  273. /// - it triggers writing all headers to output stream, such that changing any header or adding cookies will have no effect.
  274. /// - it is impossible to change an io_mode after calling this function.
  275. ///
  276. std::ostream &out();
  277. ///
  278. /// Create an HTTP time string from POSIX time as of RFC 2616
  279. ///
  280. static std::string make_http_time(time_t);
  281. ///
  282. /// Return a string that represents a message for HTTP status code \a status
  283. ///
  284. static char const *status_to_string(int status);
  285. ///
  286. /// Check if out() member function was called, (so it is impossible to do some tasks like changing HTTP headers.
  287. /// See out description for more details
  288. ///
  289. bool some_output_was_written();
  290. ///
  291. /// Finalize an output request. Generally this function is called automatically for synchronous application, however
  292. /// when working with asynchronous requests you should call this function before calling async_complete_response.
  293. ///
  294. void finalize();
  295. ///
  296. /// Defines the size of the output buffer for the output data.
  297. ///
  298. /// Setting the to 0 makes the output non-buffered and prevents unnecessary copy of large objects in memory
  299. ///
  300. /// The default is defined in configuration by service.output_buffer_size and service.async_output_buffer_size for synchronous and asynchronous
  301. /// applications accordingly, can be called before and after out() was called
  302. ///
  303. /// Calling with negative value would reset it to the default
  304. ///
  305. /// Note: when gzip compression active, buffering is still present at intermediate levels
  306. ///
  307. /// \ver{v1_2}
  308. void setbuf(int buffer_size);
  309. ///
  310. /// Sets full buffering mode for asynchronous applications
  311. ///
  312. /// When set to true the output data is transferred only when async_flush_output or async_complete_response are called this
  313. /// is the default behavior.
  314. ///
  315. /// When set to false, the data is sent upon flushing of the std::ostream provided by out(). If I/O operation blocks,
  316. /// the actual output is buffered, it is possible to test if blocking occurred by calling pending_blocked_output()
  317. ///
  318. /// When the full buffering is disable, if an error occurs, the out() is set to fail state.
  319. ///
  320. /// \ver{v1_2}
  321. void full_asynchronous_buffering(bool enable);
  322. ///
  323. /// Get current state of asynchronous buffering
  324. ///
  325. /// \ver{v1_2}
  326. bool full_asynchronous_buffering();
  327. ///
  328. /// Returns true of some of the output wasn't sent due to blocking upon flushing of std::stream &out() which is used together with full_asynchronous_buffering(false) mode.
  329. ///
  330. /// Note: it does not look on to internal buffers thus it is user's responsibility to call
  331. ///
  332. /// Once the condition occurs you can flush the output asynchronously using async_complete_response or async_flush_output
  333. ///
  334. /// \ver{v1_2}
  335. bool pending_blocked_output();
  336. /// \cond INTERNAL
  337. response(context &);
  338. ~response();
  339. /// \endcond
  340. private:
  341. friend class impl::cgi::connection;
  342. friend class ::cppcms::cache_interface;
  343. void copy_to_cache();
  344. std::string copied_data();
  345. bool need_gzip();
  346. std::pair<char const *,size_t> output();
  347. void write_http_headers(std::ostream &);
  348. int flush_async_chunk(booster::system::error_code &e);
  349. struct _data;
  350. booster::hold_ptr<_data> d;
  351. context &context_;
  352. std::ostream *stream_;
  353. io_mode_type io_mode_;
  354. uint32_t disable_compression_ : 1;
  355. uint32_t ostream_requested_ : 1;
  356. uint32_t copy_to_cache_ : 1;
  357. uint32_t finalized_ : 1;
  358. uint32_t reserved_ : 28;
  359. };
  360. } /* http */
  361. } /* cppcms */
  362. #endif