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