Boost C++ Libraries Home Libraries People FAQ More

Home | Reference | Tutorial | Examples | Design

http::server::request_parser Class Reference

List of all members.

Detailed Description

Parser for incoming requests.

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.


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 54 of file request_parser.hpp.


Constructor & Destructor Documentation

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 }


Member Function Documentation

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 }

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

00287 {
00288   return c >= 0 && c <= 127;
00289 }

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

00292 {
00293   return c >= 0 && c <= 31 || c == 127;
00294 }

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

00311 {
00312   return c >= '0' && c <= '9';
00313 }


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:
Copyright © 2003 - 2006 Christopher M. Kohlhoff

Home | Reference | Tutorial | Examples | Design