| 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 |