| 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-2015·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 5 | //·Copyright·(c)·2003-2015·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 |