| Home | Libraries | People | FAQ | More

# http/server/request_parser.cpp

Go to the documentation of this file.

    00001 #include "request_parser.hpp"
    00002 #include "request.hpp"
    00003
    00004 namespace http {
    00005 namespace server {
    00006
    00007 request_parser::request_parser()
    00008   : state_(method_start)
    00009 {
    00010 }
    00011
    00012 void request_parser::reset()
    00013 {
    00014   state_ = method_start;
    00015 }
    00016
    00017 boost::tribool request_parser::consume(request& req, char input)
    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 }
    00285
    00286 bool request_parser::is_char(int c)
    00287 {
    00288   return c >= 0 && c <= 127;
    00289 }
    00290
    00291 bool request_parser::is_ctl(int c)
    00292 {
    00293   return c >= 0 && c <= 31 || c == 127;
    00294 }
    00295
    00296 bool request_parser::is_tspecial(int c)
    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 }
    00309
    00310 bool request_parser::is_digit(int c)
    00311 {
    00312   return c >= '0' && c <= '9';
    00313 }
    00314
    00315 } // namespace server
    00316 } // namespace http

| Copyright © 2003 - 2006 Christopher M. Kohlhoff