asio 0.3.8rc3 | Home | Reference | Tutorial | Examples | Design

Examples |

# http::server::request_parser Class Reference

List of all members.

## Detailed Description

Parser for incoming requests.

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.

## Member Enumeration Documentation

enum http::server::request_parser::state`[private]`

The current state of the parser.

Enumerator:

  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 |

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,

## Constructor & Destructor Documentation

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 }

## Member Function Documentation

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 }

template<typename InputIterator>

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().

    00297 {
    00298   return c >= 0 && c <= 127;
    00299 }

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().

    00302 {
    00303   return c >= 0 && c <= 31 || c == 127;
    00304 }

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().

    00321 {
    00322   return c >= '0' && c <= '9';
    00323 }

## Member Data Documentation

enum http::server::request_parser::state http::server::request_parser::state_`[private]`

The current state of the parser.

Referenced by consume(), and reset().

The documentation for this class was generated from the following files:

- http/server/request_parser.hpp
- http/server/request_parser.cpp

asio 0.3.8rc3 | Home | Reference | Tutorial | Examples | Design