response.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * Copyright (c) 2014, Peter Thorson. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above copyright
  9. * notice, this list of conditions and the following disclaimer in the
  10. * documentation and/or other materials provided with the distribution.
  11. * * Neither the name of the WebSocket++ Project nor the
  12. * names of its contributors may be used to endorse or promote products
  13. * derived from this software without specific prior written permission.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  18. * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY
  19. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  22. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  24. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. *
  26. */
  27. #ifndef HTTP_PARSER_RESPONSE_HPP
  28. #define HTTP_PARSER_RESPONSE_HPP
  29. #include <iostream>
  30. #include <string>
  31. #include <websocketpp/http/parser.hpp>
  32. namespace websocketpp {
  33. namespace http {
  34. namespace parser {
  35. /// Stores, parses, and manipulates HTTP responses
  36. /**
  37. * http::response provides the following functionality for working with HTTP
  38. * responses.
  39. *
  40. * - Initialize response via manually setting each element
  41. * - Initialize response via reading raw bytes and parsing
  42. * - Once initialized, access individual parsed elements
  43. * - Once initialized, read entire response as raw bytes
  44. *
  45. * http::response checks for header completeness separately from the full
  46. * response. Once the header is complete, the Content-Length header is read to
  47. * determine when to stop reading body bytes. If no Content-Length is present
  48. * ready() will never return true. It is the responsibility of the caller to
  49. * consume to determine when the response is complete (ie when the connection
  50. * terminates, or some other metric).
  51. */
  52. class response : public parser {
  53. public:
  54. typedef response type;
  55. typedef lib::shared_ptr<type> ptr;
  56. response()
  57. : m_read(0)
  58. , m_buf(lib::make_shared<std::string>())
  59. , m_status_code(status_code::uninitialized)
  60. , m_state(RESPONSE_LINE) {}
  61. /// Process bytes in the input buffer
  62. /**
  63. * Process up to len bytes from input buffer buf. Returns the number of
  64. * bytes processed. Bytes left unprocessed means bytes left over after the
  65. * final header delimiters.
  66. *
  67. * Consume is a streaming processor. It may be called multiple times on one
  68. * response and the full headers need not be available before processing can
  69. * begin. If the end of the response was reached during this call to consume
  70. * the ready flag will be set. Further calls to consume once ready will be
  71. * ignored.
  72. *
  73. * Consume will throw an http::exception in the case of an error. Typical
  74. * error reasons include malformed responses, incomplete responses, and max
  75. * header size being reached.
  76. *
  77. * @param buf Pointer to byte buffer
  78. * @param len Size of byte buffer
  79. * @return Number of bytes processed.
  80. */
  81. size_t consume(char const * buf, size_t len);
  82. /// Process bytes in the input buffer (istream version)
  83. /**
  84. * Process bytes from istream s. Returns the number of bytes processed.
  85. * Bytes left unprocessed means bytes left over after the final header
  86. * delimiters.
  87. *
  88. * Consume is a streaming processor. It may be called multiple times on one
  89. * response and the full headers need not be available before processing can
  90. * begin. If the end of the response was reached during this call to consume
  91. * the ready flag will be set. Further calls to consume once ready will be
  92. * ignored.
  93. *
  94. * Consume will throw an http::exception in the case of an error. Typical
  95. * error reasons include malformed responses, incomplete responses, and max
  96. * header size being reached.
  97. *
  98. * @param buf Pointer to byte buffer
  99. * @param len Size of byte buffer
  100. * @return Number of bytes processed.
  101. */
  102. size_t consume(std::istream & s);
  103. /// Returns true if the response is ready.
  104. /**
  105. * @note will never return true if the content length header is not present
  106. */
  107. bool ready() const {
  108. return m_state == DONE;
  109. }
  110. /// Returns true if the response headers are fully parsed.
  111. bool headers_ready() const {
  112. return (m_state == BODY || m_state == DONE);
  113. }
  114. /// Returns the full raw response
  115. std::string raw() const;
  116. /// Set response status code and message
  117. /**
  118. * Sets the response status code to `code` and looks up the corresponding
  119. * message for standard codes. Non-standard codes will be entered as Unknown
  120. * use set_status(status_code::value,std::string) overload to set both
  121. * values explicitly.
  122. *
  123. * @param code Code to set
  124. * @param msg Message to set
  125. */
  126. void set_status(status_code::value code);
  127. /// Set response status code and message
  128. /**
  129. * Sets the response status code and message to independent custom values.
  130. * use set_status(status_code::value) to set the code and have the standard
  131. * message be automatically set.
  132. *
  133. * @param code Code to set
  134. * @param msg Message to set
  135. */
  136. void set_status(status_code::value code, std::string const & msg);
  137. /// Return the response status code
  138. status_code::value get_status_code() const {
  139. return m_status_code;
  140. }
  141. /// Return the response status message
  142. const std::string& get_status_msg() const {
  143. return m_status_msg;
  144. }
  145. private:
  146. /// Helper function for consume. Process response line
  147. void process(std::string::iterator begin, std::string::iterator end);
  148. /// Helper function for processing body bytes
  149. size_t process_body(char const * buf, size_t len);
  150. enum state {
  151. RESPONSE_LINE = 0,
  152. HEADERS = 1,
  153. BODY = 2,
  154. DONE = 3
  155. };
  156. std::string m_status_msg;
  157. size_t m_read;
  158. lib::shared_ptr<std::string> m_buf;
  159. status_code::value m_status_code;
  160. state m_state;
  161. };
  162. } // namespace parser
  163. } // namespace http
  164. } // namespace websocketpp
  165. #include <websocketpp/http/impl/response.hpp>
  166. #endif // HTTP_PARSER_RESPONSE_HPP