http_request_parser.cpp
Go to the documentation of this file.
1 //
2 // http_request_parser.cpp
3 // ~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
12 
13 namespace async_web_server_cpp
14 {
15 HttpRequestParser::HttpRequestParser() : state_(method_start) {}
16 
18 {
20 }
21 
22 boost::tribool HttpRequestParser::consume(HttpRequest& req, char input)
23 {
24  switch (state_)
25  {
26  case method_start:
27  if (!is_char(input) || is_ctl(input) || is_tspecial(input))
28  {
29  return false;
30  }
31  else
32  {
33  state_ = method;
34  req.method.push_back(input);
35  return boost::indeterminate;
36  }
37  case method:
38  if (input == ' ')
39  {
40  state_ = uri;
41  return boost::indeterminate;
42  }
43  else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
44  {
45  return false;
46  }
47  else
48  {
49  req.method.push_back(input);
50  return boost::indeterminate;
51  }
52  case uri:
53  if (input == ' ')
54  {
56  return boost::indeterminate;
57  }
58  else if (is_ctl(input))
59  {
60  return false;
61  }
62  else
63  {
64  req.uri.push_back(input);
65  return boost::indeterminate;
66  }
67  case http_version_h:
68  if (input == 'H')
69  {
71  return boost::indeterminate;
72  }
73  else
74  {
75  return false;
76  }
77  case http_version_t_1:
78  if (input == 'T')
79  {
81  return boost::indeterminate;
82  }
83  else
84  {
85  return false;
86  }
87  case http_version_t_2:
88  if (input == 'T')
89  {
91  return boost::indeterminate;
92  }
93  else
94  {
95  return false;
96  }
97  case http_version_p:
98  if (input == 'P')
99  {
101  return boost::indeterminate;
102  }
103  else
104  {
105  return false;
106  }
107  case http_version_slash:
108  if (input == '/')
109  {
110  req.http_version_major = 0;
111  req.http_version_minor = 0;
113  return boost::indeterminate;
114  }
115  else
116  {
117  return false;
118  }
120  if (is_digit(input))
121  {
122  req.http_version_major =
123  req.http_version_major * 10 + input - '0';
125  return boost::indeterminate;
126  }
127  else
128  {
129  return false;
130  }
131  case http_version_major:
132  if (input == '.')
133  {
135  return boost::indeterminate;
136  }
137  else if (is_digit(input))
138  {
139  req.http_version_major =
140  req.http_version_major * 10 + input - '0';
141  return boost::indeterminate;
142  }
143  else
144  {
145  return false;
146  }
148  if (is_digit(input))
149  {
150  req.http_version_minor =
151  req.http_version_minor * 10 + input - '0';
153  return boost::indeterminate;
154  }
155  else
156  {
157  return false;
158  }
159  case http_version_minor:
160  if (input == '\r')
161  {
163  return boost::indeterminate;
164  }
165  else if (is_digit(input))
166  {
167  req.http_version_minor =
168  req.http_version_minor * 10 + input - '0';
169  return boost::indeterminate;
170  }
171  else
172  {
173  return false;
174  }
175  case expecting_newline_1:
176  if (input == '\n')
177  {
179  return boost::indeterminate;
180  }
181  else
182  {
183  return false;
184  }
185  case header_line_start:
186  if (input == '\r')
187  {
189  return boost::indeterminate;
190  }
191  else if (!req.headers.empty() && (input == ' ' || input == '\t'))
192  {
193  state_ = header_lws;
194  return boost::indeterminate;
195  }
196  else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
197  {
198  return false;
199  }
200  else
201  {
202  req.headers.push_back(HttpHeader());
203  req.headers.back().name.push_back(input);
205  return boost::indeterminate;
206  }
207  case header_lws:
208  if (input == '\r')
209  {
211  return boost::indeterminate;
212  }
213  else if (input == ' ' || input == '\t')
214  {
215  return boost::indeterminate;
216  }
217  else if (is_ctl(input))
218  {
219  return false;
220  }
221  else
222  {
224  req.headers.back().value.push_back(input);
225  return boost::indeterminate;
226  }
227  case header_name:
228  if (input == ':')
229  {
231  return boost::indeterminate;
232  }
233  else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
234  {
235  return false;
236  }
237  else
238  {
239  req.headers.back().name.push_back(input);
240  return boost::indeterminate;
241  }
243  if (input == ' ')
244  {
246  return boost::indeterminate;
247  }
248  else
249  {
250  return false;
251  }
252  case header_value:
253  if (input == '\r')
254  {
256  return boost::indeterminate;
257  }
258  else if (is_ctl(input))
259  {
260  return false;
261  }
262  else
263  {
264  req.headers.back().value.push_back(input);
265  return boost::indeterminate;
266  }
267  case expecting_newline_2:
268  if (input == '\n')
269  {
271  return boost::indeterminate;
272  }
273  else
274  {
275  return false;
276  }
277  case expecting_newline_3:
278  return (input == '\n');
279  default:
280  return false;
281  }
282 }
283 
285 {
286  return c >= 0 && c <= 127;
287 }
288 
290 {
291  return (c >= 0 && c <= 31) || (c == 127);
292 }
293 
295 {
296  switch (c)
297  {
298  case '(':
299  case ')':
300  case '<':
301  case '>':
302  case '@':
303  case ',':
304  case ';':
305  case ':':
306  case '\\':
307  case '"':
308  case '/':
309  case '[':
310  case ']':
311  case '?':
312  case '=':
313  case '{':
314  case '}':
315  case ' ':
316  case '\t':
317  return true;
318  default:
319  return false;
320  }
321 }
322 
324 {
325  return c >= '0' && c <= '9';
326 }
327 
328 } // namespace async_web_server_cpp
static bool is_digit(int c)
Check if a byte is a digit.
static bool is_tspecial(int c)
Check if a byte is defined as an HTTP tspecial character.
void reset()
Reset to initial parser state.
static bool is_char(int c)
Check if a byte is an HTTP character.
HttpRequestParser()
Construct ready to parse the request method.
std::vector< HttpHeader > headers
enum async_web_server_cpp::HttpRequestParser::state state_
static bool is_ctl(int c)
Check if a byte is an HTTP control character.
boost::tribool consume(HttpRequest &req, char input)
Handle the next character of input.


async_web_server_cpp
Author(s): Mitchell Wills , Russel Toris
autogenerated on Mon Feb 28 2022 21:54:08