PageRenderTime 50ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/handler_python/wrappers.hpp

http://ahttpserver.codeplex.com
C++ Header | 302 lines | 199 code | 56 blank | 47 comment | 2 complexity | 6f8c86e32c8277fe1d1ad823b8edb4ed MD5 | raw file
  1. /*
  2. This file is part of [ahttpserver] project.
  3. Author: Artem Kustikov (kustikoff[at]tut.by)
  4. This code is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this code.
  7. Permission is granted to anyone to use this code for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this code must not be misrepresented; you must
  11. not claim that you wrote the original code. If you use this
  12. code in a product, an acknowledgment in the product documentation
  13. would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original code.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. */
  19. #ifndef PYTHON_HANDLER_WRAPPERS_H
  20. #define PYTHON_HANDLER_WRAPPERS_H
  21. #include <boost/noncopyable.hpp>
  22. #include <boost/python.hpp>
  23. #include <boost/python/suite/indexing/vector_indexing_suite.hpp>
  24. #include <boost/python/suite/indexing/map_indexing_suite.hpp>
  25. #include "aconnect/types.hpp"
  26. #include "utility.hpp"
  27. namespace python = boost::python;
  28. //////////////////////////////////////////////////////////////////////////
  29. //
  30. // Utility
  31. aconnect::string loadPythonError();
  32. //////////////////////////////////////////////////////////////////////////
  33. class TracebackLoaderWrapper : private boost::noncopyable
  34. {
  35. public:
  36. inline void write (aconnect::string_constptr data) {
  37. content += data;
  38. }
  39. aconnect::string content;
  40. };
  41. //////////////////////////////////////////////////////////////////////////
  42. //
  43. //
  44. class RequestHeaderWrapper : private boost::noncopyable
  45. {
  46. public:
  47. RequestHeaderWrapper (ahttp::HttpRequestHeader *header) : _header(header) {
  48. assert (_header);
  49. }
  50. ~RequestHeaderWrapper()
  51. {
  52. _header = NULL;
  53. }
  54. inline size_t getLength() {
  55. return _header->Headers.size();
  56. }
  57. inline std::string getHeader (aconnect::string_constptr key) const {
  58. PyThreadStateGuard guard;
  59. return _header->getHeader(key);
  60. }
  61. inline bool hasHeader (aconnect::string_constptr key) const {
  62. PyThreadStateGuard guard;
  63. return _header->hasHeader(key);
  64. }
  65. inline const aconnect::str2str_map& items () {
  66. PyThreadStateGuard guard;
  67. if (_items.size() != _header->Headers.size()) {
  68. _items.clear();
  69. std::copy (_header->Headers.begin(),
  70. _header->Headers.end(),
  71. std::inserter(_items, _items.begin()));
  72. }
  73. return _items;
  74. }
  75. inline std::string requestMethod() const { return _header->Method; }
  76. inline int requestHttpVerHigh() const { return _header->VersionHigh; }
  77. inline int requestHttpVerLow() const { return _header->VersionLow; }
  78. inline std::string userAgent() const { PyThreadStateGuard guard; return _header->getHeader ( ahttp::strings::HeaderUserAgent); }
  79. protected:
  80. ahttp::HttpRequestHeader *_header;
  81. aconnect::str2str_map _items;
  82. };
  83. //////////////////////////////////////////////////////////////////////////
  84. //
  85. //
  86. class RequestWrapper : private boost::noncopyable
  87. {
  88. public:
  89. RequestWrapper (ahttp::HttpContext *context) :
  90. _context(context),
  91. _requestGetLoaded (false),
  92. _requestPostLoaded (false),
  93. _requestReadInRawForm(false)
  94. {
  95. assert (context);
  96. }
  97. ~RequestWrapper()
  98. {
  99. _context = NULL;
  100. }
  101. inline const aconnect::str2str_map& getParameters () {
  102. processGetData(); return _context->GetParameters;
  103. }
  104. inline const aconnect::str2str_map& cookies () {
  105. processGetData(); return _context->Cookies;
  106. }
  107. inline const aconnect::str2str_map& postParameters() {
  108. processRequest(); return _context->PostParameters;
  109. }
  110. inline const std::map <aconnect::string, ahttp::UploadFileInfo>& files () {
  111. processRequest(); return _context->UploadedFiles;
  112. }
  113. inline bool isRead () { return _context->RequestStream.isRead(); }
  114. aconnect::string_constptr param (aconnect::string_constptr key);
  115. std::string read (int buffSize);
  116. std::string readline ();
  117. std::vector<std::string> readlines (int hint);
  118. void processRequest();
  119. void processGetData();
  120. protected:
  121. inline void throwRequestReadRawError () {
  122. PyErr_SetString (PyExc_RuntimeError, "HTTP request has been read in raw form");
  123. python::throw_error_already_set();
  124. }
  125. inline void throwRequestProcessedError () {
  126. PyErr_SetString (PyExc_RuntimeError, "HTTP request has been loaded to collections: use 'get' or 'post'");
  127. python::throw_error_already_set();
  128. }
  129. ahttp::HttpContext *_context;
  130. bool _requestGetLoaded;
  131. bool _requestPostLoaded;
  132. bool _requestReadInRawForm;
  133. };
  134. //////////////////////////////////////////////////////////////////////////
  135. class ResponseWriterWrapper : private boost::noncopyable
  136. {
  137. public:
  138. ResponseWriterWrapper (ahttp::HttpContext *context) :
  139. _context (context)
  140. {
  141. assert (context);
  142. }
  143. ~ResponseWriterWrapper()
  144. {
  145. _context = 0;
  146. }
  147. void write (aconnect::string_constref data);
  148. protected:
  149. ahttp::HttpContext *_context;
  150. };
  151. //////////////////////////////////////////////////////////////////////////
  152. //
  153. // wrapper for ahttp::HttpContext - cover some HttpContext functionality
  154. //
  155. class HttpContextWrapper : private boost::noncopyable
  156. {
  157. public:
  158. HttpContextWrapper (ahttp::HttpContext *context) :
  159. _context (context),
  160. _contentWritten (false),
  161. RequestHeader (context ? &context->RequestHeader : NULL),
  162. Request (context)
  163. {
  164. assert (context);
  165. }
  166. ~HttpContextWrapper()
  167. {
  168. _context = 0;
  169. }
  170. // request info
  171. inline std::string path() {
  172. return _context->RequestHeader.Path;
  173. }
  174. inline std::string virtualPath() {
  175. return _context->VirtualPath;
  176. }
  177. inline std::string initialVirtualPath() {
  178. return _context->InitialVirtualPath;
  179. }
  180. inline std::string scriptPath() {
  181. return _context->FileSystemPath.string();
  182. }
  183. // client info
  184. inline std::string clientIpAddr() {
  185. return aconnect::util::formatIpAddr (_context->Client->ip);
  186. }
  187. inline aconnect::port_type clientPort() {
  188. return _context->Client->port;
  189. }
  190. inline aconnect::port_type serverPort () {
  191. return _context->Client->server->port();
  192. }
  193. //////////////////////////////////////////////////////////////////////////
  194. inline bool isClientConnected () {
  195. return _context->isClientConnected();
  196. }
  197. inline void processServerError (aconnect::string_constptr message) {
  198. PyThreadStateGuard guard;
  199. return _context->Server->processServerError (*_context, ahttp::HttpStatus::InternalServerError, message);
  200. }
  201. inline std::string getServerVariable (aconnect::string_constptr varName) {
  202. PyThreadStateGuard guard;
  203. return _context->getServerVariable (varName);
  204. }
  205. inline aconnect::string mapPath (aconnect::string_constptr virtPath) {
  206. PyThreadStateGuard guard;
  207. return _context->mapPath (virtPath);
  208. }
  209. //////////////////////////////////////////////////////////////////////////
  210. //
  211. // response modification
  212. void write (aconnect::string_constref data);
  213. void writeEscaped (aconnect::string_constref data);
  214. void flush ();
  215. void setContentType (aconnect::string_constptr contentType, aconnect::string_constptr charset = "");
  216. inline void setUtf8Html () {
  217. return setContentType (ahttp::strings::ContentTypeTextHtml, ahttp::strings::ContentCharsetUtf8);
  218. }
  219. inline void setResponseHeader (aconnect::string_constptr header, aconnect::string_constptr value) {
  220. _context->Response.setHeader (header, value);
  221. }
  222. inline int getResponseStatus () {
  223. return _context->Response.Header.Status;
  224. }
  225. inline void setResponseStatus (int status) {
  226. _context->Response.Header.Status = status;
  227. }
  228. // WSGI - mapped to __call__
  229. PyObject* startWsgiResponse (std::string status,
  230. python::list response_headers,
  231. PyObject* exc_info = Py_None );
  232. protected:
  233. ahttp::HttpContext *_context;
  234. bool _contentWritten;
  235. public:
  236. RequestHeaderWrapper RequestHeader;
  237. RequestWrapper Request;
  238. };
  239. #endif // PYTHON_HANDLER_WRAPPERS_H