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.


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:
asio 0.3.8rc3 Home | Reference | Tutorial | Examples | Design