11 #include <boost/regex.hpp>
12 #include <boost/logic/tribool.hpp>
13 #include <pion/net/HTTPParser.hpp>
14 #include <pion/net/HTTPRequest.hpp>
15 #include <pion/net/HTTPResponse.hpp>
16 #include <pion/net/HTTPMessage.hpp>
36 HTTPParser::ErrorCategory * HTTPParser::m_error_category_ptr = NULL;
37 boost::once_flag HTTPParser::m_instance_flag = BOOST_ONCE_INIT;
43 boost::system::error_code& ec)
45 PION_ASSERT(!
eof() );
47 boost::tribool rc = boost::indeterminate;
48 std::size_t total_bytes_parsed = 0;
51 http_msg.setDataAfterMissingPacket(
true);
55 switch (m_message_parse_state) {
58 m_message_parse_state = PARSE_HEADERS;
64 total_bytes_parsed += m_bytes_last_read;
75 total_bytes_parsed += m_bytes_last_read;
85 total_bytes_parsed += m_bytes_last_read;
89 case PARSE_CONTENT_NO_LENGTH:
91 total_bytes_parsed += m_bytes_last_read;
99 }
while ( boost::indeterminate(rc) && !
eof() );
103 m_message_parse_state = PARSE_END;
105 }
else if(rc ==
false) {
110 m_bytes_last_read = total_bytes_parsed;
116 std::size_t len, boost::system::error_code& ec)
118 static const char MISSING_DATA_CHAR =
'X';
119 boost::tribool rc = boost::indeterminate;
123 switch (m_message_parse_state) {
128 setError(ec, ERROR_MISSING_HEADER_DATA);
135 if (m_chunked_content_parse_state == PARSE_CHUNK
136 && m_bytes_read_in_current_chunk < m_size_of_current_chunk
137 && (m_size_of_current_chunk - m_bytes_read_in_current_chunk) >= len)
140 for (std::size_t n = 0; n < len && http_msg.
getChunkCache().size() < m_max_content_length; ++n)
143 m_bytes_read_in_current_chunk += len;
144 m_bytes_last_read = len;
145 m_bytes_total_read += len;
146 m_bytes_content_read += len;
148 if (m_bytes_read_in_current_chunk == m_size_of_current_chunk) {
149 m_chunked_content_parse_state = PARSE_EXPECTING_CR_AFTER_CHUNK;
153 setError(ec, ERROR_MISSING_CHUNK_DATA);
161 if (m_bytes_content_remaining == 0) {
164 }
else if (m_bytes_content_remaining < len) {
166 setError(ec, ERROR_MISSING_TOO_MUCH_CONTENT);
171 if ( (m_bytes_content_read+len) <= m_max_content_length) {
173 for (std::size_t n = 0; n < len; ++n)
174 http_msg.
getContent()[m_bytes_content_read++] = MISSING_DATA_CHAR;
176 m_bytes_content_read += len;
179 m_bytes_content_remaining -= len;
180 m_bytes_total_read += len;
181 m_bytes_last_read = len;
183 if (m_bytes_content_remaining == 0)
189 case PARSE_CONTENT_NO_LENGTH:
191 for (std::size_t n = 0; n < len && http_msg.
getChunkCache().size() < m_max_content_length; ++n)
193 m_bytes_last_read = len;
194 m_bytes_total_read += len;
195 m_bytes_content_read += len;
206 m_message_parse_state = PARSE_END;
208 }
else if(rc ==
false) {
216 boost::system::error_code& ec)
226 m_bytes_last_read = 0;
229 if (m_save_raw_headers)
232 switch (m_headers_parse_state) {
233 case PARSE_METHOD_START:
240 m_headers_parse_state = PARSE_METHOD;
250 m_headers_parse_state = PARSE_URI_STEM;
265 m_headers_parse_state = PARSE_HTTP_VERSION_H;
267 m_query_string.erase();
268 m_headers_parse_state = PARSE_URI_QUERY;
272 m_headers_parse_state = PARSE_EXPECTING_NEWLINE;
276 m_headers_parse_state = PARSE_EXPECTING_CR;
288 case PARSE_URI_QUERY:
291 m_headers_parse_state = PARSE_HTTP_VERSION_H;
303 case PARSE_HTTP_VERSION_H:
313 m_headers_parse_state = PARSE_EXPECTING_NEWLINE;
322 m_headers_parse_state = PARSE_EXPECTING_CR;
327 m_headers_parse_state = PARSE_HTTP_VERSION_T_1;
330 case PARSE_HTTP_VERSION_T_1:
336 m_headers_parse_state = PARSE_HTTP_VERSION_T_2;
339 case PARSE_HTTP_VERSION_T_2:
345 m_headers_parse_state = PARSE_HTTP_VERSION_P;
348 case PARSE_HTTP_VERSION_P:
354 m_headers_parse_state = PARSE_HTTP_VERSION_SLASH;
357 case PARSE_HTTP_VERSION_SLASH:
363 m_headers_parse_state = PARSE_HTTP_VERSION_MAJOR_START;
366 case PARSE_HTTP_VERSION_MAJOR_START:
373 m_headers_parse_state = PARSE_HTTP_VERSION_MAJOR;
376 case PARSE_HTTP_VERSION_MAJOR:
379 m_headers_parse_state = PARSE_HTTP_VERSION_MINOR_START;
389 case PARSE_HTTP_VERSION_MINOR_START:
396 m_headers_parse_state = PARSE_HTTP_VERSION_MINOR;
399 case PARSE_HTTP_VERSION_MINOR:
404 m_headers_parse_state = PARSE_STATUS_CODE_START;
412 m_headers_parse_state = PARSE_EXPECTING_NEWLINE;
419 m_headers_parse_state = PARSE_EXPECTING_CR;
429 case PARSE_STATUS_CODE_START:
436 m_headers_parse_state = PARSE_STATUS_CODE;
439 case PARSE_STATUS_CODE:
442 m_status_message.erase();
443 m_headers_parse_state = PARSE_STATUS_MESSAGE;
445 m_status_code = ( (m_status_code * 10) + (*
m_read_ptr -
'0') );
448 m_status_message.erase();
449 m_headers_parse_state = PARSE_EXPECTING_NEWLINE;
452 m_status_message.erase();
453 m_headers_parse_state = PARSE_EXPECTING_CR;
460 case PARSE_STATUS_MESSAGE:
463 m_headers_parse_state = PARSE_EXPECTING_NEWLINE;
465 m_headers_parse_state = PARSE_EXPECTING_CR;
477 case PARSE_EXPECTING_NEWLINE:
480 m_headers_parse_state = PARSE_HEADER_START;
486 m_bytes_last_read = (
m_read_ptr - read_start_ptr);
487 m_bytes_total_read += m_bytes_last_read;
490 m_headers_parse_state = PARSE_HEADER_WHITESPACE;
496 m_header_name.erase();
498 m_headers_parse_state = PARSE_HEADER_NAME;
502 case PARSE_EXPECTING_CR:
505 m_headers_parse_state = PARSE_HEADER_START;
511 m_bytes_last_read = (
m_read_ptr - read_start_ptr);
512 m_bytes_total_read += m_bytes_last_read;
515 m_headers_parse_state = PARSE_HEADER_WHITESPACE;
521 m_header_name.erase();
523 m_headers_parse_state = PARSE_HEADER_NAME;
527 case PARSE_HEADER_WHITESPACE:
530 m_headers_parse_state = PARSE_EXPECTING_NEWLINE;
532 m_headers_parse_state = PARSE_EXPECTING_CR;
538 m_header_name.erase();
540 m_headers_parse_state = PARSE_HEADER_NAME;
544 case PARSE_HEADER_START:
547 m_headers_parse_state = PARSE_EXPECTING_FINAL_NEWLINE;
549 m_headers_parse_state = PARSE_EXPECTING_FINAL_CR;
551 m_headers_parse_state = PARSE_HEADER_WHITESPACE;
557 m_header_name.erase();
559 m_headers_parse_state = PARSE_HEADER_NAME;
563 case PARSE_HEADER_NAME:
566 m_header_value.erase();
567 m_headers_parse_state = PARSE_SPACE_BEFORE_HEADER_VALUE;
572 setError(ec, ERROR_HEADER_NAME_SIZE);
580 case PARSE_SPACE_BEFORE_HEADER_VALUE:
583 m_headers_parse_state = PARSE_HEADER_VALUE;
585 http_msg.
addHeader(m_header_name, m_header_value);
586 m_headers_parse_state = PARSE_EXPECTING_NEWLINE;
588 http_msg.
addHeader(m_header_name, m_header_value);
589 m_headers_parse_state = PARSE_EXPECTING_CR;
596 m_headers_parse_state = PARSE_HEADER_VALUE;
600 case PARSE_HEADER_VALUE:
603 http_msg.
addHeader(m_header_name, m_header_value);
604 m_headers_parse_state = PARSE_EXPECTING_NEWLINE;
606 http_msg.
addHeader(m_header_name, m_header_value);
607 m_headers_parse_state = PARSE_EXPECTING_CR;
612 setError(ec, ERROR_HEADER_VALUE_SIZE);
620 case PARSE_EXPECTING_FINAL_NEWLINE:
622 m_bytes_last_read = (
m_read_ptr - read_start_ptr);
623 m_bytes_total_read += m_bytes_last_read;
626 case PARSE_EXPECTING_FINAL_CR:
628 m_bytes_last_read = (
m_read_ptr - read_start_ptr);
629 m_bytes_total_read += m_bytes_last_read;
636 m_bytes_last_read = (
m_read_ptr - read_start_ptr);
637 m_bytes_total_read += m_bytes_last_read;
638 return boost::indeterminate;
647 HTTPRequest& http_request(dynamic_cast<HTTPRequest&>(http_msg));
653 if (! m_query_string.empty()) {
655 m_query_string.c_str(),
656 m_query_string.size()))
657 PION_LOG_WARN(
m_logger,
"Request query string parsing failed (URI)");
661 std::pair<HTTPTypes::Headers::const_iterator, HTTPTypes::Headers::const_iterator>
662 cookie_pair = http_request.
getHeaders().equal_range(HTTPTypes::HEADER_COOKIE);
663 for (HTTPTypes::Headers::const_iterator cookie_iterator = cookie_pair.first;
664 cookie_iterator != http_request.
getHeaders().end()
665 && cookie_iterator != cookie_pair.second; ++cookie_iterator)
668 cookie_iterator->second,
false) )
669 PION_LOG_WARN(
m_logger,
"Cookie header parsing failed");
676 HTTPResponse& http_response(dynamic_cast<HTTPResponse&>(http_msg));
681 std::pair<HTTPTypes::Headers::const_iterator, HTTPTypes::Headers::const_iterator>
682 cookie_pair = http_response.
getHeaders().equal_range(HTTPTypes::HEADER_SET_COOKIE);
683 for (HTTPTypes::Headers::const_iterator cookie_iterator = cookie_pair.first;
684 cookie_iterator != http_response.
getHeaders().end()
685 && cookie_iterator != cookie_pair.second; ++cookie_iterator)
688 cookie_iterator->second,
true) )
689 PION_LOG_WARN(
m_logger,
"Set-Cookie header parsing failed");
696 boost::system::error_code& ec)
698 boost::tribool rc = boost::indeterminate;
700 m_bytes_content_remaining = m_bytes_content_read = 0;
708 m_message_parse_state = PARSE_CHUNKS;
711 if (m_parse_headers_only)
717 m_message_parse_state = PARSE_END;
723 if (http_msg.
hasHeader(HTTPTypes::HEADER_CONTENT_LENGTH)) {
729 PION_LOG_ERROR(
m_logger,
"Unable to update content length");
730 setError(ec, ERROR_INVALID_CONTENT_LENGTH);
736 m_message_parse_state = PARSE_END;
739 m_message_parse_state = PARSE_CONTENT;
743 if (m_bytes_content_remaining > m_max_content_length)
747 if (m_parse_headers_only)
761 m_message_parse_state = PARSE_CONTENT_NO_LENGTH;
764 if (m_parse_headers_only)
767 m_message_parse_state = PARSE_END;
780 const char *ptr,
const size_t len)
783 enum QueryParseState {
784 QUERY_PARSE_NAME, QUERY_PARSE_VALUE
785 } parse_state = QUERY_PARSE_NAME;
788 const char *
const end = ptr + len;
789 std::string query_name;
790 std::string query_value;
794 switch (parse_state) {
796 case QUERY_PARSE_NAME:
800 parse_state = QUERY_PARSE_VALUE;
801 }
else if (*ptr ==
'&') {
803 if (! query_name.empty()) {
805 dict.insert( std::make_pair(query_name, query_value) );
808 }
else if (*ptr ==
'\r' || *ptr ==
'\n' || *ptr ==
'\t') {
810 }
else if (isControl(*ptr) || query_name.size() >=
QUERY_NAME_MAX) {
815 query_name.push_back(*ptr);
819 case QUERY_PARSE_VALUE:
823 if (! query_name.empty()) {
824 dict.insert( std::make_pair(query_name, query_value) );
828 parse_state = QUERY_PARSE_NAME;
829 }
else if (*ptr ==
'\r' || *ptr ==
'\n' || *ptr ==
'\t') {
836 query_value.push_back(*ptr);
845 if (! query_name.empty())
846 dict.insert( std::make_pair(query_name, query_value) );
852 const char *ptr,
const size_t len,
853 bool set_cookie_header)
862 enum CookieParseState {
863 COOKIE_PARSE_NAME, COOKIE_PARSE_VALUE, COOKIE_PARSE_IGNORE
864 } parse_state = COOKIE_PARSE_NAME;
867 const char *
const end = ptr + len;
868 std::string cookie_name;
869 std::string cookie_value;
870 char value_quote_character =
'\0';
874 switch (parse_state) {
876 case COOKIE_PARSE_NAME:
880 value_quote_character =
'\0';
881 parse_state = COOKIE_PARSE_VALUE;
882 }
else if (*ptr ==
';' || *ptr ==
',') {
885 if (! cookie_name.empty()) {
887 if (! isCookieAttribute(cookie_name, set_cookie_header))
888 dict.insert( std::make_pair(cookie_name, cookie_value) );
891 }
else if (*ptr !=
' ') {
896 cookie_name.push_back(*ptr);
900 case COOKIE_PARSE_VALUE:
902 if (value_quote_character ==
'\0') {
904 if (*ptr ==
';' || *ptr ==
',') {
906 if (! isCookieAttribute(cookie_name, set_cookie_header))
907 dict.insert( std::make_pair(cookie_name, cookie_value) );
909 cookie_value.erase();
910 parse_state = COOKIE_PARSE_NAME;
911 }
else if (*ptr ==
'\'' || *ptr ==
'"') {
912 if (cookie_value.empty()) {
914 value_quote_character = *ptr;
920 cookie_value.push_back(*ptr);
922 }
else if (*ptr !=
' ' || !cookie_value.empty()) {
927 cookie_value.push_back(*ptr);
931 if (*ptr == value_quote_character) {
933 if (! isCookieAttribute(cookie_name, set_cookie_header))
934 dict.insert( std::make_pair(cookie_name, cookie_value) );
936 cookie_value.erase();
937 parse_state = COOKIE_PARSE_IGNORE;
943 cookie_value.push_back(*ptr);
948 case COOKIE_PARSE_IGNORE:
950 if (*ptr ==
';' || *ptr ==
',')
951 parse_state = COOKIE_PARSE_NAME;
959 if (! isCookieAttribute(cookie_name, set_cookie_header))
960 dict.insert( std::make_pair(cookie_name, cookie_value) );
966 boost::system::error_code& ec)
976 m_bytes_last_read = 0;
979 switch (m_chunked_content_parse_state) {
980 case PARSE_CHUNK_SIZE_START:
983 m_chunk_size_str.erase();
985 m_chunked_content_parse_state = PARSE_CHUNK_SIZE;
996 case PARSE_CHUNK_SIZE:
1000 m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE;
1004 m_chunked_content_parse_state = PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE;
1011 case PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE:
1013 m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE;
1024 case PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE:
1028 m_bytes_read_in_current_chunk = 0;
1029 m_size_of_current_chunk = strtol(m_chunk_size_str.c_str(), 0, 16);
1030 if (m_size_of_current_chunk == 0) {
1031 m_chunked_content_parse_state = PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK;
1033 m_chunked_content_parse_state = PARSE_CHUNK;
1042 if (m_bytes_read_in_current_chunk < m_size_of_current_chunk) {
1043 if (chunk_cache.size() < m_max_content_length)
1045 m_bytes_read_in_current_chunk++;
1047 if (m_bytes_read_in_current_chunk == m_size_of_current_chunk) {
1048 m_chunked_content_parse_state = PARSE_EXPECTING_CR_AFTER_CHUNK;
1052 case PARSE_EXPECTING_CR_AFTER_CHUNK:
1055 m_chunked_content_parse_state = PARSE_EXPECTING_LF_AFTER_CHUNK;
1062 case PARSE_EXPECTING_LF_AFTER_CHUNK:
1065 m_chunked_content_parse_state = PARSE_CHUNK_SIZE_START;
1072 case PARSE_EXPECTING_FINAL_CR_AFTER_LAST_CHUNK:
1075 m_chunked_content_parse_state = PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK;
1082 case PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK:
1086 m_bytes_last_read = (
m_read_ptr - read_start_ptr);
1087 m_bytes_total_read += m_bytes_last_read;
1088 m_bytes_content_read += m_bytes_last_read;
1089 PION_LOG_DEBUG(
m_logger,
"Parsed " << m_bytes_last_read <<
" chunked payload content bytes; chunked content complete.");
1100 m_bytes_last_read = (
m_read_ptr - read_start_ptr);
1101 m_bytes_total_read += m_bytes_last_read;
1102 m_bytes_content_read += m_bytes_last_read;
1103 return boost::indeterminate;
1107 boost::system::error_code& ec)
1109 size_t content_bytes_to_read;
1111 boost::tribool rc = boost::indeterminate;
1113 if (m_bytes_content_remaining == 0) {
1117 if (content_bytes_available >= m_bytes_content_remaining) {
1120 content_bytes_to_read = m_bytes_content_remaining;
1123 content_bytes_to_read = content_bytes_available;
1125 m_bytes_content_remaining -= content_bytes_to_read;
1129 if (m_bytes_content_read < m_max_content_length) {
1130 if (m_bytes_content_read + content_bytes_to_read > m_max_content_length) {
1134 m_max_content_length - m_bytes_content_read);
1142 m_bytes_content_read += content_bytes_to_read;
1143 m_bytes_total_read += content_bytes_to_read;
1144 m_bytes_last_read = content_bytes_to_read;
1152 m_bytes_last_read = 0;
1156 if (chunk_cache.size() < m_max_content_length)
1160 m_bytes_total_read += m_bytes_last_read;
1161 m_bytes_content_read += m_bytes_last_read;
1163 return m_bytes_last_read;
1168 switch (m_message_parse_state) {
1189 http_msg.
setIsValid(m_chunked_content_parse_state==PARSE_CHUNK_SIZE_START);
1192 case PARSE_CONTENT_NO_LENGTH:
1204 HTTPRequest& http_request(dynamic_cast<HTTPRequest&>(http_msg));
1205 const std::string& content_type_header = http_request.
getHeader(HTTPTypes::HEADER_CONTENT_TYPE);
1206 if (content_type_header.compare(0, HTTPTypes::CONTENT_TYPE_URLENCODED.length(),
1207 HTTPTypes::CONTENT_TYPE_URLENCODED) == 0)
1212 PION_LOG_WARN(
m_logger,
"Request query string parsing failed (POST content)");
1223 HTTPMessage::STATUS_PARTIAL : HTTPMessage::STATUS_TRUNCATED;
1225 st = msg_parsed_ok ? HTTPMessage::STATUS_OK : HTTPMessage::STATUS_TRUNCATED;
1228 http_msg.setStatus(st);
1234 m_error_category_ptr = &UNIQUE_ERROR_CATEGORY;
1240 static const boost::regex IPV4_ADDR_RX(
"[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}");
1247 static const boost::regex PRIVATE_NET_RX(
"(10\\.[0-9]{1,3}|127\\.[0-9]{1,3}|192\\.168|172\\.1[6-9]|172\\.2[0-9]|172\\.3[0-1])\\.[0-9]{1,3}\\.[0-9]{1,3}");
1254 boost::match_results<std::string::const_iterator> m;
1255 std::string::const_iterator start_it = header.begin();
1258 while (boost::regex_search(start_it, header.end(), m, IPV4_ADDR_RX)) {
1260 std::string ip_str(m[0].first, m[0].second);
1262 if (! boost::regex_match(ip_str, PRIVATE_NET_RX) ) {
1268 start_it = m[0].second;
void setStatusCode(unsigned int n)
sets the HTTP response status code
boost::tribool parse(HTTPMessage &http_msg, boost::system::error_code &ec)
void setMissingPackets(bool newVal)
set to true when missing packets detected
void addHeader(const std::string &key, const std::string &value)
adds a value for the HTTP header named key
static void setError(boost::system::error_code &ec, ErrorValue ev)
static bool parseForwardedFor(const std::string &header, std::string &public_ip)
static const boost::uint32_t METHOD_MAX
maximum length for the request method
static const boost::uint32_t QUERY_NAME_MAX
maximum length for the name of a query string variable
QueryParams & getQueryParams(void)
returns the query parameters
static void createErrorCategory(void)
creates the unique HTTPParser ErrorCategory
std::size_t consumeContentAsNextChunk(HTTPMessage::ChunkCache &chunk_buffers)
boost::tribool parseChunks(HTTPMessage::ChunkCache &chunk_buffers, boost::system::error_code &ec)
const std::string & getHeader(const std::string &key) const
returns a value for the header if any are defined; otherwise, an empty string
CookieParams & getCookieParams(void)
returns the cookie parameters
const bool m_is_request
true if the message is an HTTP request; false if it is an HTTP response
Headers & getHeaders(void)
returns a reference to the HTTP headers
class-specific error category
void concatenateChunks(void)
bool hasDataAfterMissingPackets() const
true if more data seen after the missing packets
static const boost::uint32_t COOKIE_VALUE_MAX
maximum length for the value of a cookie; also used for path and domain
static const boost::uint32_t RESOURCE_MAX
maximum length for the resource requested
void setResource(const std::string &str)
sets the resource or uri-stem originally requested
static bool parseURLEncoded(HTTPTypes::QueryParams &dict, const char *ptr, const std::size_t len)
static const boost::uint32_t HEADER_VALUE_MAX
maximum length for an HTTP header value
static const std::size_t DEFAULT_CONTENT_MAX
maximum length for HTTP payload content
StringDictionary QueryParams
data type for HTTP query parameters
void setVersionMajor(const boost::uint16_t n)
sets the major HTTP version number
static const boost::uint32_t HEADER_NAME_MAX
maximum length for an HTTP header name
void updateMessageWithHeaderData(HTTPMessage &http_msg) const
std::size_t getContentLength(void) const
returns the length of the payload content (in bytes)
char * createContentBuffer(void)
static const boost::uint32_t COOKIE_NAME_MAX
maximum length for the name of a cookie name
StringDictionary CookieParams
data type for HTTP cookie parameters
virtual bool isContentLengthImplied(void) const =0
should return true if the content length can be implied without headers
boost::tribool parseMissingData(HTTPMessage &http_msg, std::size_t len, boost::system::error_code &ec)
boost::uint16_t getVersionMajor(void) const
returns the major HTTP version number
boost::tribool parseHeaders(HTTPMessage &http_msg, boost::system::error_code &ec)
void updateContentLengthUsingHeader(void)
sets the length of the payload content using the Content-Length header
DataStatus
defines message data integrity status codes
ChunkCache & getChunkCache(void)
returns a reference to the chunk cache
bool hasMissingPackets() const
true if there were missing packets
bool hasHeader(const std::string &key) const
returns true if at least one value for the header is defined
void setContentLength(const std::size_t n)
sets the length of the payload content (in bytes)
void setStatusMessage(const std::string &msg)
sets the HTTP response status message
std::size_t getContentBytesRead(void) const
returns the total number of bytes read while parsing the payload content
static void computeMsgStatus(HTTPMessage &http_msg, bool msg_parsed_ok)
boost::tribool consumeContent(HTTPMessage &http_msg, boost::system::error_code &ec)
void finish(HTTPMessage &http_msg) const
static const boost::uint32_t QUERY_VALUE_MAX
maximum length for the value of a query string variable
static const boost::uint32_t STATUS_MESSAGE_MAX
maximum length for response status message
void setIsValid(bool b=true)
sets whether or not the message is valid
static const boost::uint32_t QUERY_STRING_MAX
maximum length for the query string
boost::uint16_t getVersionMinor(void) const
returns the minor HTTP version number
std::size_t bytes_available(void) const
returns the number of bytes available in the read buffer
PionLogger m_logger
primary logging interface used by this class
static bool parseCookieHeader(HTTPTypes::CookieParams &dict, const char *ptr, const std::size_t len, bool set_cookie_header)
const char * m_read_ptr
points to the next character to be consumed in the read_buffer
boost::tribool finishHeaderParsing(HTTPMessage &http_msg, boost::system::error_code &ec)
std::vector< char > ChunkCache
used to cache chunked data
void updateTransferCodingUsingHeader(void)
sets the transfer coding using the Transfer-Encoding header
bool eof(void) const
returns true if there are no more bytes available in the read buffer
void setVersionMinor(const boost::uint16_t n)
sets the minor HTTP version number
const char * m_read_end_ptr
points to the end of the read_buffer (last byte + 1)
void setQueryString(const std::string &str)
sets the uri-query or query string requested
bool isChunked(void) const
returns true if the message content is chunked
bool isValid(void) const
returns true if the message is valid
bool isParsingRequest(void) const
returns true if the parser is being used to parse an HTTP request
char * getContent(void)
returns a pointer to the payload content, or NULL if there is none
void setMethod(const std::string &str)
sets the HTTP request method (i.e. GET, POST, PUT)