5 // Copyright (c) 2003-2017 Christopher M. Kohlhoff (chris at kohlhoff dot com)
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)
11 #include "request_parser.hpp"
12 #include "request.hpp"
17 request_parser::request_parser()
18 : state_(method_start
)
22 void request_parser::reset()
24 state_
= method_start
;
27 boost::tribool
request_parser::consume(request
& req
, char input
)
32 if (!is_char(input
) || is_ctl(input
) || is_tspecial(input
))
39 req
.method
.push_back(input
);
40 return boost::indeterminate
;
46 return boost::indeterminate
;
48 else if (!is_char(input
) || is_ctl(input
) || is_tspecial(input
))
54 req
.method
.push_back(input
);
55 return boost::indeterminate
;
60 state_
= http_version_h
;
61 return boost::indeterminate
;
63 else if (is_ctl(input
))
69 req
.uri
.push_back(input
);
70 return boost::indeterminate
;
75 state_
= http_version_t_1
;
76 return boost::indeterminate
;
82 case http_version_t_1
:
85 state_
= http_version_t_2
;
86 return boost::indeterminate
;
92 case http_version_t_2
:
95 state_
= http_version_p
;
96 return boost::indeterminate
;
105 state_
= http_version_slash
;
106 return boost::indeterminate
;
112 case http_version_slash
:
115 req
.http_version_major
= 0;
116 req
.http_version_minor
= 0;
117 state_
= http_version_major_start
;
118 return boost::indeterminate
;
124 case http_version_major_start
:
127 req
.http_version_major
= req
.http_version_major
* 10 + input
- '0';
128 state_
= http_version_major
;
129 return boost::indeterminate
;
135 case http_version_major
:
138 state_
= http_version_minor_start
;
139 return boost::indeterminate
;
141 else if (is_digit(input
))
143 req
.http_version_major
= req
.http_version_major
* 10 + input
- '0';
144 return boost::indeterminate
;
150 case http_version_minor_start
:
153 req
.http_version_minor
= req
.http_version_minor
* 10 + input
- '0';
154 state_
= http_version_minor
;
155 return boost::indeterminate
;
161 case http_version_minor
:
164 state_
= expecting_newline_1
;
165 return boost::indeterminate
;
167 else if (is_digit(input
))
169 req
.http_version_minor
= req
.http_version_minor
* 10 + input
- '0';
170 return boost::indeterminate
;
176 case expecting_newline_1
:
179 state_
= header_line_start
;
180 return boost::indeterminate
;
186 case header_line_start
:
189 state_
= expecting_newline_3
;
190 return boost::indeterminate
;
192 else if (!req
.headers
.empty() && (input
== ' ' || input
== '\t'))
195 return boost::indeterminate
;
197 else if (!is_char(input
) || is_ctl(input
) || is_tspecial(input
))
203 req
.headers
.push_back(header());
204 req
.headers
.back().name
.push_back(input
);
205 state_
= header_name
;
206 return boost::indeterminate
;
211 state_
= expecting_newline_2
;
212 return boost::indeterminate
;
214 else if (input
== ' ' || input
== '\t')
216 return boost::indeterminate
;
218 else if (is_ctl(input
))
224 state_
= header_value
;
225 req
.headers
.back().value
.push_back(input
);
226 return boost::indeterminate
;
231 state_
= space_before_header_value
;
232 return boost::indeterminate
;
234 else if (!is_char(input
) || is_ctl(input
) || is_tspecial(input
))
240 req
.headers
.back().name
.push_back(input
);
241 return boost::indeterminate
;
243 case space_before_header_value
:
246 state_
= header_value
;
247 return boost::indeterminate
;
256 state_
= expecting_newline_2
;
257 return boost::indeterminate
;
259 else if (is_ctl(input
))
265 req
.headers
.back().value
.push_back(input
);
266 return boost::indeterminate
;
268 case expecting_newline_2
:
271 state_
= header_line_start
;
272 return boost::indeterminate
;
278 case expecting_newline_3
:
279 return (input
== '\n');
285 bool request_parser::is_char(int c
)
287 return c
>= 0 && c
<= 127;
290 bool request_parser::is_ctl(int c
)
292 return (c
>= 0 && c
<= 31) || (c
== 127);
295 bool request_parser::is_tspecial(int c
)
299 case '(': case ')': case '<': case '>': case '@':
300 case ',': case ';': case ':': case '\\': case '"':
301 case '/': case '[': case ']': case '?': case '=':
302 case '{': case '}': case ' ': case '\t':
309 bool request_parser::is_digit(int c
)
311 return c
>= '0' && c
<= '9';
314 } // namespace server3