![]() |
Home | Libraries | People | FAQ | More |
Definition at line 13 of file request_parser.hpp.
Public Member Functions | |
request_parser () | |
Construct ready to parse the request method. | |
void | reset () |
Reset to initial parser state. | |
template<typename InputIterator> | |
boost::tuple< boost::tribool, InputIterator > | parse (request &req, InputIterator begin, InputIterator end) |
Parse some data. The tribool return value is true when a complete request has been parsed, false if the data is invalid, indeterminate when more data is required. The InputIterator return value indicates how much of the input has been consumed. | |
Private Types | |
method_start | |
method | |
uri_start | |
uri | |
http_version_h | |
http_version_t_1 | |
http_version_t_2 | |
http_version_p | |
http_version_slash | |
http_version_major_start | |
http_version_major | |
http_version_minor_start | |
http_version_minor | |
expecting_newline_1 | |
header_line_start | |
header_lws | |
header_name | |
space_before_header_value | |
header_value | |
expecting_newline_2 | |
expecting_newline_3 | |
enum | state { method_start, method, uri_start, uri, http_version_h, http_version_t_1, http_version_t_2, http_version_p, http_version_slash, http_version_major_start, http_version_major, http_version_minor_start, http_version_minor, expecting_newline_1, header_line_start, header_lws, header_name, space_before_header_value, header_value, expecting_newline_2, expecting_newline_3 } |
The current state of the parser. More... | |
Private Member Functions | |
boost::tribool | consume (request &req, char input) |
Handle the next character of input. | |
Static Private Member Functions | |
static bool | is_char (int c) |
Check if a byte is an HTTP character. | |
static bool | is_ctl (int c) |
Check if a byte is an HTTP control character. | |
static bool | is_tspecial (int c) |
Check if a byte is defined as an HTTP tspecial character. | |
static bool | is_digit (int c) |
Check if a byte is a digit. | |
Private Attributes | |
enum http::server::request_parser::state | state_ |
The current state of the parser. |
enum http::server::request_parser::state [private] |
The current state of the parser.
Definition at line 54 of file request_parser.hpp.
00058 { 00059 method_start, 00060 method, 00061 uri_start, 00062 uri, 00063 http_version_h, 00064 http_version_t_1, 00065 http_version_t_2, 00066 http_version_p, 00067 http_version_slash, 00068 http_version_major_start, 00069 http_version_major, 00070 http_version_minor_start, 00071 http_version_minor, 00072 expecting_newline_1, 00073 header_line_start, 00074 header_lws, 00075 header_name, 00076 space_before_header_value, 00077 header_value,
http::server::request_parser::request_parser | ( | ) |
Construct ready to parse the request method.
Definition at line 7 of file request_parser.cpp.
00008 : state_(method_start) 00009 { 00010 }
void http::server::request_parser::reset | ( | ) |
Reset to initial parser state.
Definition at line 12 of file request_parser.cpp.
00013 { 00014 state_ = method_start; 00015 }
boost::tuple<boost::tribool, InputIterator> http::server::request_parser::parse | ( | request & | req, | |
InputIterator | begin, | |||
InputIterator | end | |||
) |
Parse some data. The tribool return value is true when a complete request has been parsed, false if the data is invalid, indeterminate when more data is required. The InputIterator return value indicates how much of the input has been consumed.
Definition at line 24 of file request_parser.hpp.
Referenced by http::server::connection::handle_read().
00029 { 00030 while (begin != end) 00031 { 00032 boost::tribool result = consume(req, *begin++); 00033 if (result || !result) 00034 return boost::make_tuple(result, begin); 00035 }
boost::tribool http::server::request_parser::consume | ( | request & | req, | |
char | input | |||
) | [private] |
Handle the next character of input.
Definition at line 17 of file request_parser.cpp.
00018 { 00019 switch (state_) 00020 { 00021 case method_start: 00022 if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00023 { 00024 return false; 00025 } 00026 else 00027 { 00028 state_ = method; 00029 req.method.push_back(input); 00030 return boost::indeterminate; 00031 } 00032 case method: 00033 if (input == ' ') 00034 { 00035 state_ = uri; 00036 return boost::indeterminate; 00037 } 00038 else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00039 { 00040 return false; 00041 } 00042 else 00043 { 00044 req.method.push_back(input); 00045 return boost::indeterminate; 00046 } 00047 case uri_start: 00048 if (is_ctl(input)) 00049 { 00050 return false; 00051 } 00052 else 00053 { 00054 state_ = uri; 00055 req.uri.push_back(input); 00056 return boost::indeterminate; 00057 } 00058 case uri: 00059 if (input == ' ') 00060 { 00061 state_ = http_version_h; 00062 return boost::indeterminate; 00063 } 00064 else if (is_ctl(input)) 00065 { 00066 return false; 00067 } 00068 else 00069 { 00070 req.uri.push_back(input); 00071 return boost::indeterminate; 00072 } 00073 case http_version_h: 00074 if (input == 'H') 00075 { 00076 state_ = http_version_t_1; 00077 return boost::indeterminate; 00078 } 00079 else 00080 { 00081 return false; 00082 } 00083 case http_version_t_1: 00084 if (input == 'T') 00085 { 00086 state_ = http_version_t_2; 00087 return boost::indeterminate; 00088 } 00089 else 00090 { 00091 return false; 00092 } 00093 case http_version_t_2: 00094 if (input == 'T') 00095 { 00096 state_ = http_version_p; 00097 return boost::indeterminate; 00098 } 00099 else 00100 { 00101 return false; 00102 } 00103 case http_version_p: 00104 if (input == 'P') 00105 { 00106 state_ = http_version_slash; 00107 return boost::indeterminate; 00108 } 00109 else 00110 { 00111 return false; 00112 } 00113 case http_version_slash: 00114 if (input == '/') 00115 { 00116 req.http_version_major = 0; 00117 req.http_version_minor = 0; 00118 state_ = http_version_major_start; 00119 return boost::indeterminate; 00120 } 00121 else 00122 { 00123 return false; 00124 } 00125 case http_version_major_start: 00126 if (is_digit(input)) 00127 { 00128 req.http_version_major = req.http_version_major * 10 + input - '0'; 00129 state_ = http_version_major; 00130 return boost::indeterminate; 00131 } 00132 else 00133 { 00134 return false; 00135 } 00136 case http_version_major: 00137 if (input == '.') 00138 { 00139 state_ = http_version_minor_start; 00140 return boost::indeterminate; 00141 } 00142 else if (is_digit(input)) 00143 { 00144 req.http_version_major = req.http_version_major * 10 + input - '0'; 00145 return boost::indeterminate; 00146 } 00147 else 00148 { 00149 return false; 00150 } 00151 case http_version_minor_start: 00152 if (is_digit(input)) 00153 { 00154 req.http_version_minor = req.http_version_minor * 10 + input - '0'; 00155 state_ = http_version_minor; 00156 return boost::indeterminate; 00157 } 00158 else 00159 { 00160 return false; 00161 } 00162 case http_version_minor: 00163 if (input == '\r') 00164 { 00165 state_ = expecting_newline_1; 00166 return boost::indeterminate; 00167 } 00168 else if (is_digit(input)) 00169 { 00170 req.http_version_minor = req.http_version_minor * 10 + input - '0'; 00171 return boost::indeterminate; 00172 } 00173 else 00174 { 00175 return false; 00176 } 00177 case expecting_newline_1: 00178 if (input == '\n') 00179 { 00180 state_ = header_line_start; 00181 return boost::indeterminate; 00182 } 00183 else 00184 { 00185 return false; 00186 } 00187 case header_line_start: 00188 if (input == '\r') 00189 { 00190 state_ = expecting_newline_3; 00191 return boost::indeterminate; 00192 } 00193 else if (!req.headers.empty() && (input == ' ' || input == '\t')) 00194 { 00195 state_ = header_lws; 00196 return boost::indeterminate; 00197 } 00198 else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00199 { 00200 return false; 00201 } 00202 else 00203 { 00204 req.headers.push_back(header()); 00205 req.headers.back().name.push_back(input); 00206 state_ = header_name; 00207 return boost::indeterminate; 00208 } 00209 case header_lws: 00210 if (input == '\r') 00211 { 00212 state_ = expecting_newline_2; 00213 return boost::indeterminate; 00214 } 00215 else if (input == ' ' || input == '\t') 00216 { 00217 return boost::indeterminate; 00218 } 00219 else if (is_ctl(input)) 00220 { 00221 return false; 00222 } 00223 else 00224 { 00225 state_ = header_value; 00226 req.headers.back().value.push_back(input); 00227 return boost::indeterminate; 00228 } 00229 case header_name: 00230 if (input == ':') 00231 { 00232 state_ = space_before_header_value; 00233 return boost::indeterminate; 00234 } 00235 else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00236 { 00237 return false; 00238 } 00239 else 00240 { 00241 req.headers.back().name.push_back(input); 00242 return boost::indeterminate; 00243 } 00244 case space_before_header_value: 00245 if (input == ' ') 00246 { 00247 state_ = header_value; 00248 return boost::indeterminate; 00249 } 00250 else 00251 { 00252 return false; 00253 } 00254 case header_value: 00255 if (input == '\r') 00256 { 00257 state_ = expecting_newline_2; 00258 return boost::indeterminate; 00259 } 00260 else if (is_ctl(input)) 00261 { 00262 return false; 00263 } 00264 else 00265 { 00266 req.headers.back().value.push_back(input); 00267 return boost::indeterminate; 00268 } 00269 case expecting_newline_2: 00270 if (input == '\n') 00271 { 00272 state_ = header_line_start; 00273 return boost::indeterminate; 00274 } 00275 else 00276 { 00277 return false; 00278 } 00279 case expecting_newline_3: 00280 return (input == '\n'); 00281 default: 00282 return false; 00283 } 00284 }
bool http::server::request_parser::is_char | ( | int | c | ) | [static, private] |
Check if a byte is an HTTP character.
Definition at line 286 of file request_parser.cpp.
Referenced by consume().
bool http::server::request_parser::is_ctl | ( | int | c | ) | [static, private] |
Check if a byte is an HTTP control character.
Definition at line 291 of file request_parser.cpp.
Referenced by consume().
bool http::server::request_parser::is_tspecial | ( | int | c | ) | [static, private] |
Check if a byte is defined as an HTTP tspecial character.
Definition at line 296 of file request_parser.cpp.
Referenced by consume().
00297 { 00298 switch (c) 00299 { 00300 case '(': case ')': case '<': case '>': case '@': 00301 case ',': case ';': case ':': case '\\': case '"': 00302 case '/': case '[': case ']': case '?': case '=': 00303 case '{': case '}': case ' ': case '\t': 00304 return true; 00305 default: 00306 return false; 00307 } 00308 }
bool http::server::request_parser::is_digit | ( | int | c | ) | [static, private] |
Check if a byte is a digit.
Definition at line 310 of file request_parser.cpp.
Referenced by consume().
Copyright © 2003 - 2006 Christopher M. Kohlhoff |