Examples |
Definition at line 23 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 | |
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 64 of file request_parser.hpp.
00068 { 00069 method_start, 00070 method, 00071 uri_start, 00072 uri, 00073 http_version_h, 00074 http_version_t_1, 00075 http_version_t_2, 00076 http_version_p, 00077 http_version_slash, 00078 http_version_major_start, 00079 http_version_major, 00080 http_version_minor_start, 00081 http_version_minor, 00082 expecting_newline_1, 00083 header_line_start, 00084 header_lws, 00085 header_name, 00086 space_before_header_value, 00087 header_value,
http::server::request_parser::request_parser | ( | ) |
Construct ready to parse the request method.
Definition at line 17 of file request_parser.cpp.
00018 : state_(method_start) 00019 { 00020 }
void http::server::request_parser::reset | ( | ) |
Reset to initial parser state.
Definition at line 22 of file request_parser.cpp.
00023 { 00024 state_ = method_start; 00025 }
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 34 of file request_parser.hpp.
Referenced by http::server::connection::handle_read().
00039 { 00040 while (begin != end) 00041 { 00042 boost::tribool result = consume(req, *begin++); 00043 if (result || !result) 00044 return boost::make_tuple(result, begin); 00045 }
boost::tribool http::server::request_parser::consume | ( | request & | req, | |
char | input | |||
) | [private] |
Handle the next character of input.
Definition at line 27 of file request_parser.cpp.
00028 { 00029 switch (state_) 00030 { 00031 case method_start: 00032 if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00033 { 00034 return false; 00035 } 00036 else 00037 { 00038 state_ = method; 00039 req.method.push_back(input); 00040 return boost::indeterminate; 00041 } 00042 case method: 00043 if (input == ' ') 00044 { 00045 state_ = uri; 00046 return boost::indeterminate; 00047 } 00048 else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00049 { 00050 return false; 00051 } 00052 else 00053 { 00054 req.method.push_back(input); 00055 return boost::indeterminate; 00056 } 00057 case uri_start: 00058 if (is_ctl(input)) 00059 { 00060 return false; 00061 } 00062 else 00063 { 00064 state_ = uri; 00065 req.uri.push_back(input); 00066 return boost::indeterminate; 00067 } 00068 case uri: 00069 if (input == ' ') 00070 { 00071 state_ = http_version_h; 00072 return boost::indeterminate; 00073 } 00074 else if (is_ctl(input)) 00075 { 00076 return false; 00077 } 00078 else 00079 { 00080 req.uri.push_back(input); 00081 return boost::indeterminate; 00082 } 00083 case http_version_h: 00084 if (input == 'H') 00085 { 00086 state_ = http_version_t_1; 00087 return boost::indeterminate; 00088 } 00089 else 00090 { 00091 return false; 00092 } 00093 case http_version_t_1: 00094 if (input == 'T') 00095 { 00096 state_ = http_version_t_2; 00097 return boost::indeterminate; 00098 } 00099 else 00100 { 00101 return false; 00102 } 00103 case http_version_t_2: 00104 if (input == 'T') 00105 { 00106 state_ = http_version_p; 00107 return boost::indeterminate; 00108 } 00109 else 00110 { 00111 return false; 00112 } 00113 case http_version_p: 00114 if (input == 'P') 00115 { 00116 state_ = http_version_slash; 00117 return boost::indeterminate; 00118 } 00119 else 00120 { 00121 return false; 00122 } 00123 case http_version_slash: 00124 if (input == '/') 00125 { 00126 req.http_version_major = 0; 00127 req.http_version_minor = 0; 00128 state_ = http_version_major_start; 00129 return boost::indeterminate; 00130 } 00131 else 00132 { 00133 return false; 00134 } 00135 case http_version_major_start: 00136 if (is_digit(input)) 00137 { 00138 req.http_version_major = req.http_version_major * 10 + input - '0'; 00139 state_ = http_version_major; 00140 return boost::indeterminate; 00141 } 00142 else 00143 { 00144 return false; 00145 } 00146 case http_version_major: 00147 if (input == '.') 00148 { 00149 state_ = http_version_minor_start; 00150 return boost::indeterminate; 00151 } 00152 else if (is_digit(input)) 00153 { 00154 req.http_version_major = req.http_version_major * 10 + input - '0'; 00155 return boost::indeterminate; 00156 } 00157 else 00158 { 00159 return false; 00160 } 00161 case http_version_minor_start: 00162 if (is_digit(input)) 00163 { 00164 req.http_version_minor = req.http_version_minor * 10 + input - '0'; 00165 state_ = http_version_minor; 00166 return boost::indeterminate; 00167 } 00168 else 00169 { 00170 return false; 00171 } 00172 case http_version_minor: 00173 if (input == '\r') 00174 { 00175 state_ = expecting_newline_1; 00176 return boost::indeterminate; 00177 } 00178 else if (is_digit(input)) 00179 { 00180 req.http_version_minor = req.http_version_minor * 10 + input - '0'; 00181 return boost::indeterminate; 00182 } 00183 else 00184 { 00185 return false; 00186 } 00187 case expecting_newline_1: 00188 if (input == '\n') 00189 { 00190 state_ = header_line_start; 00191 return boost::indeterminate; 00192 } 00193 else 00194 { 00195 return false; 00196 } 00197 case header_line_start: 00198 if (input == '\r') 00199 { 00200 state_ = expecting_newline_3; 00201 return boost::indeterminate; 00202 } 00203 else if (!req.headers.empty() && (input == ' ' || input == '\t')) 00204 { 00205 state_ = header_lws; 00206 return boost::indeterminate; 00207 } 00208 else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00209 { 00210 return false; 00211 } 00212 else 00213 { 00214 req.headers.push_back(header()); 00215 req.headers.back().name.push_back(input); 00216 state_ = header_name; 00217 return boost::indeterminate; 00218 } 00219 case header_lws: 00220 if (input == '\r') 00221 { 00222 state_ = expecting_newline_2; 00223 return boost::indeterminate; 00224 } 00225 else if (input == ' ' || input == '\t') 00226 { 00227 return boost::indeterminate; 00228 } 00229 else if (is_ctl(input)) 00230 { 00231 return false; 00232 } 00233 else 00234 { 00235 state_ = header_value; 00236 req.headers.back().value.push_back(input); 00237 return boost::indeterminate; 00238 } 00239 case header_name: 00240 if (input == ':') 00241 { 00242 state_ = space_before_header_value; 00243 return boost::indeterminate; 00244 } 00245 else if (!is_char(input) || is_ctl(input) || is_tspecial(input)) 00246 { 00247 return false; 00248 } 00249 else 00250 { 00251 req.headers.back().name.push_back(input); 00252 return boost::indeterminate; 00253 } 00254 case space_before_header_value: 00255 if (input == ' ') 00256 { 00257 state_ = header_value; 00258 return boost::indeterminate; 00259 } 00260 else 00261 { 00262 return false; 00263 } 00264 case header_value: 00265 if (input == '\r') 00266 { 00267 state_ = expecting_newline_2; 00268 return boost::indeterminate; 00269 } 00270 else if (is_ctl(input)) 00271 { 00272 return false; 00273 } 00274 else 00275 { 00276 req.headers.back().value.push_back(input); 00277 return boost::indeterminate; 00278 } 00279 case expecting_newline_2: 00280 if (input == '\n') 00281 { 00282 state_ = header_line_start; 00283 return boost::indeterminate; 00284 } 00285 else 00286 { 00287 return false; 00288 } 00289 case expecting_newline_3: 00290 return (input == '\n'); 00291 default: 00292 return false; 00293 } 00294 }
bool http::server::request_parser::is_char | ( | int | c | ) | [static, private] |
Check if a byte is an HTTP character.
Definition at line 296 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 301 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 306 of file request_parser.cpp.
Referenced by consume().
00307 { 00308 switch (c) 00309 { 00310 case '(': case ')': case '<': case '>': case '@': 00311 case ',': case ';': case ':': case '\\': case '"': 00312 case '/': case '[': case ']': case '?': case '=': 00313 case '{': case '}': case ' ': case '\t': 00314 return true; 00315 default: 00316 return false; 00317 } 00318 }
bool http::server::request_parser::is_digit | ( | int | c | ) | [static, private] |
Check if a byte is a digit.
Definition at line 320 of file request_parser.cpp.
Referenced by consume().