websocketpp  0.4.0
C++/Boost Asio based websocket client/server library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
parser.hpp
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 
28 #ifndef HTTP_PARSER_IMPL_HPP
29 #define HTTP_PARSER_IMPL_HPP
30 
31 #include <algorithm>
32 #include <sstream>
33 #include <string>
34 
35 namespace websocketpp {
36 namespace http {
37 namespace parser {
38 
39 inline void parser::set_version(std::string const & version) {
40  m_version = version;
41 }
42 
43 inline std::string const & parser::get_header(std::string const & key) const {
44  header_list::const_iterator h = m_headers.find(key);
45 
46  if (h == m_headers.end()) {
47  return empty_header;
48  } else {
49  return h->second;
50  }
51 }
52 
53 inline bool parser::get_header_as_plist(std::string const & key,
54  parameter_list & out) const
55 {
56  header_list::const_iterator it = m_headers.find(key);
57 
58  if (it == m_headers.end() || it->second.size() == 0) {
59  return false;
60  }
61 
62  return this->parse_parameter_list(it->second,out);
63 }
64 
65 inline void parser::append_header(std::string const & key, std::string const &
66  val)
67 {
68  if (std::find_if(key.begin(),key.end(),is_not_token_char) != key.end()) {
69  throw exception("Invalid header name",status_code::bad_request);
70  }
71 
72  if (this->get_header(key) == "") {
73  m_headers[key] = val;
74  } else {
75  m_headers[key] += ", " + val;
76  }
77 }
78 
79 inline void parser::replace_header(std::string const & key, std::string const &
80  val)
81 {
82  m_headers[key] = val;
83 }
84 
85 inline void parser::remove_header(std::string const & key) {
86  m_headers.erase(key);
87 }
88 
89 inline void parser::set_body(std::string const & value) {
90  if (value.size() == 0) {
91  remove_header("Content-Length");
92  m_body = "";
93  return;
94  }
95 
96  std::stringstream len;
97  len << value.size();
98  replace_header("Content-Length", len.str());
99  m_body = value;
100 }
101 
102 inline bool parser::parse_parameter_list(std::string const & in,
103  parameter_list & out) const
104 {
105  if (in.size() == 0) {
106  return false;
107  }
108 
109  std::string::const_iterator it;
110  it = extract_parameters(in.begin(),in.end(),out);
111  return (it == in.begin());
112 }
113 
114 inline bool parser::parse_headers(std::istream & s) {
115  std::string header;
116  std::string::size_type end;
117 
118  // get headers
119  while (std::getline(s, header) && header != "\r") {
120  if (header[header.size()-1] != '\r') {
121  continue; // ignore malformed header lines?
122  } else {
123  header.erase(header.end()-1);
124  }
125 
126  end = header.find(header_separator,0);
127 
128  if (end != std::string::npos) {
129  append_header(header.substr(0,end),header.substr(end+2));
130  }
131  }
132 
133  return true;
134 }
135 
136 inline void parser::process_header(std::string::iterator begin,
137  std::string::iterator end)
138 {
139  std::string::iterator cursor = std::search(
140  begin,
141  end,
143  header_separator + sizeof(header_separator) - 1
144  );
145 
146  if (cursor == end) {
147  throw exception("Invalid header line",status_code::bad_request);
148  }
149 
150  append_header(strip_lws(std::string(begin,cursor)),
151  strip_lws(std::string(cursor+sizeof(header_separator)-1,end)));
152 }
153 
154 inline std::string parser::raw_headers() const {
155  std::stringstream raw;
156 
157  header_list::const_iterator it;
158  for (it = m_headers.begin(); it != m_headers.end(); it++) {
159  raw << it->first << ": " << it->second << "\r\n";
160  }
161 
162  return raw.str();
163 }
164 
165 
166 
167 } // namespace parser
168 } // namespace http
169 } // namespace websocketpp
170 
171 #endif // HTTP_PARSER_IMPL_HPP
uint16_t value
The type of a close code value.
Definition: close.hpp:49
static std::string const empty_header
Literal value of an empty header.
Definition: constants.hpp:60
bool parse_parameter_list(std::string const &in, parameter_list &out) const
Extract an HTTP parameter list from a string.
Definition: parser.hpp:102
std::vector< std::pair< std::string, attribute_list > > parameter_list
The type of an HTTP parameter list.
Definition: constants.hpp:51
bool is_not_token_char(unsigned char c)
Is the character a non-token.
Definition: constants.hpp:98
std::string const & get_header(std::string const &key) const
Get the value of an HTTP header.
Definition: parser.hpp:43
static char const header_separator[]
Literal value of the HTTP header separator.
Definition: constants.hpp:57
Namespace for the WebSocket++ project.
Definition: base64.hpp:41
void append_header(std::string const &key, std::string const &val)
Append a value to an existing HTTP header.
Definition: parser.hpp:65
void replace_header(std::string const &key, std::string const &val)
Set a value for an HTTP header, replacing an existing value.
Definition: parser.hpp:79
void remove_header(std::string const &key)
Remove a header from the parser.
Definition: parser.hpp:85