request_parser.cc 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. //
  2. // request_parser.cpp
  3. // ~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2010 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #include "Experimental/http_server/request_parser.h"
  11. #include "Experimental/http_server/request.h"
  12. namespace http_server {
  13. request_parser::request_parser() :
  14. state_(method_start)
  15. {
  16. }
  17. void request_parser::reset()
  18. {
  19. state_ = method_start;
  20. }
  21. boost::tribool request_parser::consume(request& req, char input)
  22. {
  23. switch (state_)
  24. {
  25. case method_start:
  26. if (!is_char(input) || is_ctl(input) || is_tspecial(input))
  27. {
  28. return false;
  29. }
  30. else
  31. {
  32. state_ = method;
  33. req.method.push_back(input);
  34. return boost::indeterminate;
  35. }
  36. case method:
  37. if (input == ' ')
  38. {
  39. state_ = uri;
  40. return boost::indeterminate;
  41. }
  42. else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
  43. {
  44. return false;
  45. }
  46. else
  47. {
  48. req.method.push_back(input);
  49. return boost::indeterminate;
  50. }
  51. case uri_start:
  52. if (is_ctl(input))
  53. {
  54. return false;
  55. }
  56. else
  57. {
  58. state_ = uri;
  59. req.uri.push_back(input);
  60. return boost::indeterminate;
  61. }
  62. case uri:
  63. if (input == ' ')
  64. {
  65. state_ = http_version_h;
  66. return boost::indeterminate;
  67. }
  68. else if (is_ctl(input))
  69. {
  70. return false;
  71. }
  72. else
  73. {
  74. req.uri.push_back(input);
  75. return boost::indeterminate;
  76. }
  77. case http_version_h:
  78. if (input == 'H')
  79. {
  80. state_ = http_version_t_1;
  81. return boost::indeterminate;
  82. }
  83. else
  84. {
  85. return false;
  86. }
  87. case http_version_t_1:
  88. if (input == 'T')
  89. {
  90. state_ = http_version_t_2;
  91. return boost::indeterminate;
  92. }
  93. else
  94. {
  95. return false;
  96. }
  97. case http_version_t_2:
  98. if (input == 'T')
  99. {
  100. state_ = http_version_p;
  101. return boost::indeterminate;
  102. }
  103. else
  104. {
  105. return false;
  106. }
  107. case http_version_p:
  108. if (input == 'P')
  109. {
  110. state_ = http_version_slash;
  111. return boost::indeterminate;
  112. }
  113. else
  114. {
  115. return false;
  116. }
  117. case http_version_slash:
  118. if (input == '/')
  119. {
  120. req.http_version_major = 0;
  121. req.http_version_minor = 0;
  122. state_ = http_version_major_start;
  123. return boost::indeterminate;
  124. }
  125. else
  126. {
  127. return false;
  128. }
  129. case http_version_major_start:
  130. if (is_digit(input))
  131. {
  132. req.http_version_major = req.http_version_major * 10 + input
  133. - '0';
  134. state_ = http_version_major;
  135. return boost::indeterminate;
  136. }
  137. else
  138. {
  139. return false;
  140. }
  141. case http_version_major:
  142. if (input == '.')
  143. {
  144. state_ = http_version_minor_start;
  145. return boost::indeterminate;
  146. }
  147. else if (is_digit(input))
  148. {
  149. req.http_version_major = req.http_version_major * 10 + input
  150. - '0';
  151. return boost::indeterminate;
  152. }
  153. else
  154. {
  155. return false;
  156. }
  157. case http_version_minor_start:
  158. if (is_digit(input))
  159. {
  160. req.http_version_minor = req.http_version_minor * 10 + input
  161. - '0';
  162. state_ = http_version_minor;
  163. return boost::indeterminate;
  164. }
  165. else
  166. {
  167. return false;
  168. }
  169. case http_version_minor:
  170. if (input == '\r')
  171. {
  172. state_ = expecting_newline_1;
  173. return boost::indeterminate;
  174. }
  175. else if (is_digit(input))
  176. {
  177. req.http_version_minor = req.http_version_minor * 10 + input
  178. - '0';
  179. return boost::indeterminate;
  180. }
  181. else
  182. {
  183. return false;
  184. }
  185. case expecting_newline_1:
  186. if (input == '\n')
  187. {
  188. state_ = header_line_start;
  189. return boost::indeterminate;
  190. }
  191. else
  192. {
  193. return false;
  194. }
  195. case header_line_start:
  196. if (input == '\r')
  197. {
  198. state_ = expecting_newline_3;
  199. return boost::indeterminate;
  200. }
  201. else if (!req.headers.empty() && (input == ' ' || input == '\t'))
  202. {
  203. state_ = header_lws;
  204. return boost::indeterminate;
  205. }
  206. else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
  207. {
  208. return false;
  209. }
  210. else
  211. {
  212. req.headers.push_back(header());
  213. req.headers.back().name.push_back(input);
  214. state_ = header_name;
  215. return boost::indeterminate;
  216. }
  217. case header_lws:
  218. if (input == '\r')
  219. {
  220. state_ = expecting_newline_2;
  221. return boost::indeterminate;
  222. }
  223. else if (input == ' ' || input == '\t')
  224. {
  225. return boost::indeterminate;
  226. }
  227. else if (is_ctl(input))
  228. {
  229. return false;
  230. }
  231. else
  232. {
  233. state_ = header_value;
  234. req.headers.back().value.push_back(input);
  235. return boost::indeterminate;
  236. }
  237. case header_name:
  238. if (input == ':')
  239. {
  240. state_ = space_before_header_value;
  241. return boost::indeterminate;
  242. }
  243. else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
  244. {
  245. return false;
  246. }
  247. else
  248. {
  249. req.headers.back().name.push_back(input);
  250. return boost::indeterminate;
  251. }
  252. case space_before_header_value:
  253. if (input == ' ')
  254. {
  255. state_ = header_value;
  256. return boost::indeterminate;
  257. }
  258. else
  259. {
  260. return false;
  261. }
  262. case header_value:
  263. if (input == '\r')
  264. {
  265. state_ = expecting_newline_2;
  266. return boost::indeterminate;
  267. }
  268. else if (is_ctl(input))
  269. {
  270. return false;
  271. }
  272. else
  273. {
  274. req.headers.back().value.push_back(input);
  275. return boost::indeterminate;
  276. }
  277. case expecting_newline_2:
  278. if (input == '\n')
  279. {
  280. state_ = header_line_start;
  281. return boost::indeterminate;
  282. }
  283. else
  284. {
  285. return false;
  286. }
  287. case expecting_newline_3:
  288. return (input == '\n');
  289. default:
  290. return false;
  291. }
  292. }
  293. bool request_parser::is_char(int c)
  294. {
  295. return c >= 0 && c <= 127;
  296. }
  297. bool request_parser::is_ctl(int c)
  298. {
  299. return (c >= 0 && c <= 31) || (c == 127);
  300. }
  301. bool request_parser::is_tspecial(int c)
  302. {
  303. switch (c)
  304. {
  305. case '(':
  306. case ')':
  307. case '<':
  308. case '>':
  309. case '@':
  310. case ',':
  311. case ';':
  312. case ':':
  313. case '\\':
  314. case '"':
  315. case '/':
  316. case '[':
  317. case ']':
  318. case '?':
  319. case '=':
  320. case '{':
  321. case '}':
  322. case ' ':
  323. case '\t':
  324. return true;
  325. default:
  326. return false;
  327. }
  328. }
  329. bool request_parser::is_digit(int c)
  330. {
  331. return c >= '0' && c <= '9';
  332. }
  333. } // namespace http_server