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