alaCarte Maps
Renderer for OpenStreetMap tiles
request_parser.cpp
Go to the documentation of this file.
1 
22 //
23 // request_parser.cpp
24 // ~~~~~~~~~~~~~~~~~~
25 //
26 // Copyright (c) 2003-2012 Christopher M. Kohlhoff (chris at kohlhoff dot com)
27 //
28 // Distributed under the Boost Software License, Version 1.0. (See accompanying
29 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
30 //
31 
33 #include "server/http_request.hpp"
34 
36  : state_ ( method_start )
37 {
38 }
39 
41 {
43 }
44 
45 boost::tribool HttpRequestParser::consume ( shared_ptr<HttpRequest> req, char input )
46 {
47  switch ( state_ ) {
48  case method_start:
49 
50  if ( !is_char ( input ) || is_ctl ( input ) || is_tspecial ( input ) ) {
51  return false;
52  } else {
53  state_ = method;
54  req->data.method.push_back ( input );
55  return boost::indeterminate;
56  }
57 
58  case method:
59 
60  if ( input == ' ' ) {
61  state_ = uri;
62  return boost::indeterminate;
63  } else if ( !is_char ( input ) || is_ctl ( input ) || is_tspecial ( input ) ) {
64  return false;
65  } else {
66  req->data.method.push_back ( input );
67  return boost::indeterminate;
68  }
69 
70  case uri:
71 
72  if ( input == ' ' ) {
74  return boost::indeterminate;
75  } else if ( is_ctl ( input ) ) {
76  return false;
77  } else {
78  req->data.uri.push_back ( input );
79  return boost::indeterminate;
80  }
81 
82  case http_version_h:
83 
84  if ( input == 'H' ) {
86  return boost::indeterminate;
87  } else {
88  return false;
89  }
90 
91  case http_version_t_1:
92 
93  if ( input == 'T' ) {
95  return boost::indeterminate;
96  } else {
97  return false;
98  }
99 
100  case http_version_t_2:
101 
102  if ( input == 'T' ) {
104  return boost::indeterminate;
105  } else {
106  return false;
107  }
108 
109  case http_version_p:
110 
111  if ( input == 'P' ) {
113  return boost::indeterminate;
114  } else {
115  return false;
116  }
117 
118  case http_version_slash:
119 
120  if ( input == '/' ) {
121  req->data.http_version_major = 0;
122  req->data.http_version_minor = 0;
124  return boost::indeterminate;
125  } else {
126  return false;
127  }
128 
130 
131  if ( is_digit ( input ) ) {
132  req->data.http_version_major = req->data.http_version_major * 10 + input - '0';
134  return boost::indeterminate;
135  } else {
136  return false;
137  }
138 
139  case http_version_major:
140 
141  if ( input == '.' ) {
143  return boost::indeterminate;
144  } else if ( is_digit ( input ) ) {
145  req->data.http_version_major = req->data.http_version_major * 10 + input - '0';
146  return boost::indeterminate;
147  } else {
148  return false;
149  }
150 
152 
153  if ( is_digit ( input ) ) {
154  req->data.http_version_minor = req->data.http_version_minor * 10 + input - '0';
156  return boost::indeterminate;
157  } else {
158  return false;
159  }
160 
161  case http_version_minor:
162 
163  if ( input == '\r' ) {
165  return boost::indeterminate;
166  } else if ( is_digit ( input ) ) {
167  req->data.http_version_minor = req->data.http_version_minor * 10 + input - '0';
168  return boost::indeterminate;
169  } else {
170  return false;
171  }
172 
173  case expecting_newline_1:
174 
175  if ( input == '\n' ) {
177  return boost::indeterminate;
178  } else {
179  return false;
180  }
181 
182  case header_line_start:
183 
184  if ( input == '\r' ) {
186  return boost::indeterminate;
187  } else if ( !req->data.headers.empty() && ( input == ' ' || input == '\t' ) ) {
188  state_ = header_lws;
189  return boost::indeterminate;
190  } else if ( !is_char ( input ) || is_ctl ( input ) || is_tspecial ( input ) ) {
191  return false;
192  } else {
193  req->data.headers.push_back ( HttpRequest::Header() );
194  req->data.headers.back().name.push_back ( input );
196  return boost::indeterminate;
197  }
198 
199  case header_lws:
200 
201  if ( input == '\r' ) {
203  return boost::indeterminate;
204  } else if ( input == ' ' || input == '\t' ) {
205  return boost::indeterminate;
206  } else if ( is_ctl ( input ) ) {
207  return false;
208  } else {
210  req->data.headers.back().value.push_back ( input );
211  return boost::indeterminate;
212  }
213 
214  case header_name:
215 
216  if ( input == ':' ) {
218  return boost::indeterminate;
219  } else if ( !is_char ( input ) || is_ctl ( input ) || is_tspecial ( input ) ) {
220  return false;
221  } else {
222  req->data.headers.back().name.push_back ( input );
223  return boost::indeterminate;
224  }
225 
227 
228  if ( input == ' ' ) {
230  return boost::indeterminate;
231  } else {
232  return false;
233  }
234 
235  case header_value:
236 
237  if ( input == '\r' ) {
239  return boost::indeterminate;
240  } else if ( is_ctl ( input ) ) {
241  return false;
242  } else {
243  req->data.headers.back().value.push_back ( input );
244  return boost::indeterminate;
245  }
246 
247  case expecting_newline_2:
248 
249  if ( input == '\n' ) {
251  return boost::indeterminate;
252  } else {
253  return false;
254  }
255 
256  case expecting_newline_3:
257  return ( input == '\n' );
258  default:
259  return false;
260  }
261 }
262 
264 {
265  return c >= 0 && c <= 127;
266 }
267 
269 {
270  return ( c >= 0 && c <= 31 ) || ( c == 127 );
271 }
272 
274 {
275  switch ( c ) {
276  case '(':
277  case ')':
278  case '<':
279  case '>':
280  case '@':
281  case ',':
282  case ';':
283  case ':':
284  case '\\':
285  case '"':
286  case '/':
287  case '[':
288  case ']':
289  case '?':
290  case '=':
291  case '{':
292  case '}':
293  case ' ':
294  case '\t':
295  return true;
296  default:
297  return false;
298  }
299 }
300 
302 {
303  return c >= '0' && c <= '9';
304 }
305 
static bool is_tspecial(int c)
Check if a byte is defined as an HTTP tspecial character.
HttpRequestParser()
Construct ready to parse the request method.
static bool is_ctl(int c)
Check if a byte is an HTTP control character.
static bool is_digit(int c)
Check if a byte is a digit.
static bool is_char(int c)
Check if a byte is an HTTP character.
enum HttpRequestParser::state state_
boost::tribool consume(shared_ptr< HttpRequest > req, char input)
Handle the next character of input.
void reset()
Reset to initial parser state.