| src/examples/cpp03/http/server/request_handler.cpp | src/examples/cpp11/http/server/request_handler.cpp | 
| ⋮ | ⋮ | 
| 1  | // | 1  | // | 
| 2  | //·request_handler.cpp | 2  | //·request_handler.cpp | 
| 3  | //·~~~~~~~~~~~~~~~~~~~ | 3  | //·~~~~~~~~~~~~~~~~~~~ | 
| 4  | // | 4  | // | 
| 5  | //·Copyright·(c)·2003-2018·Christopher·M.·Kohlhoff·(chris·at·kohlhoff·dot·com) | 5  | //·Copyright·(c)·2003-2018·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_handler.hpp" | 11  | #include·"request_handler.hpp" | 
| 12  | #include·<fstream> | 12  | #include·<fstream> | 
| 13  | #include·<sstream> | 13  | #include·<sstream> | 
| 14  | #include·<string> | 14  | #include·<string> | 
| 15  | #include·<boost/lexical_cast.hpp> |  | 
| 16  | #include·"mime_types.hpp" | 15  | #include·"mime_types.hpp" | 
| 17  | #include·"reply.hpp" | 16  | #include·"reply.hpp" | 
| 18  | #include·"request.hpp" | 17  | #include·"request.hpp" | 
| 19  |  | 18  |  | 
| 20  | namespace·http·{ | 19  | namespace·http·{ | 
| 21  | namespace·server·{ | 20  | namespace·server·{ | 
| 22  |  | 21  |  | 
| 23  | request_handler::request_handler(const·std::string&·doc_root) | 22  | request_handler::request_handler(const·std::string&·doc_root) | 
| 24  | ··:·doc_root_(doc_root) | 23  | ··:·doc_root_(doc_root) | 
| 25  | { | 24  | { | 
| 26  | } | 25  | } | 
| 27  |  | 26  |  | 
| 28  | void·request_handler::handle_request(const·request&·req,·reply&·rep) | 27  | void·request_handler::handle_request(const·request&·req,·reply&·rep) | 
| 29  | { | 28  | { | 
| 30  | ··//·Decode·url·to·path. | 29  | ··//·Decode·url·to·path. | 
| 31  | ··std::string·request_path; | 30  | ··std::string·request_path; | 
| 32  | ··if·(!url_decode(req.uri,·request_path)) | 31  | ··if·(!url_decode(req.uri,·request_path)) | 
| 33  | ··{ | 32  | ··{ | 
| 34  | ····rep·=·reply::stock_reply(reply::bad_request); | 33  | ····rep·=·reply::stock_reply(reply::bad_request); | 
| 35  | ····return; | 34  | ····return; | 
| 36  | ··} | 35  | ··} | 
| 37  |  | 36  |  | 
| 38  | ··//·Request·path·must·be·absolute·and·not·contain·"..". | 37  | ··//·Request·path·must·be·absolute·and·not·contain·"..". | 
| 39  | ··if·(request_path.empty()·||·request_path[0]·!=·'/' | 38  | ··if·(request_path.empty()·||·request_path[0]·!=·'/' | 
| 40  | ······||·request_path.find("..")·!=·std::string::npos) | 39  | ······||·request_path.find("..")·!=·std::string::npos) | 
| 41  | ··{ | 40  | ··{ | 
| 42  | ····rep·=·reply::stock_reply(reply::bad_request); | 41  | ····rep·=·reply::stock_reply(reply::bad_request); | 
| 43  | ····return; | 42  | ····return; | 
| 44  | ··} | 43  | ··} | 
| 45  |  | 44  |  | 
| 46  | ··//·If·path·ends·in·slash·(i.e.·is·a·directory)·then·add·"index.html". | 45  | ··//·If·path·ends·in·slash·(i.e.·is·a·directory)·then·add·"index.html". | 
| 47  | ··if·(request_path[request_path.size()·-·1]·==·'/') | 46  | ··if·(request_path[request_path.size()·-·1]·==·'/') | 
| 48  | ··{ | 47  | ··{ | 
| 49  | ····request_path·+=·"index.html"; | 48  | ····request_path·+=·"index.html"; | 
| 50  | ··} | 49  | ··} | 
| 51  |  | 50  |  | 
| 52  | ··//·Determine·the·file·extension. | 51  | ··//·Determine·the·file·extension. | 
| 53  | ··std::size_t·last_slash_pos·=·request_path.find_last_of("/"); | 52  | ··std::size_t·last_slash_pos·=·request_path.find_last_of("/"); | 
| 54  | ··std::size_t·last_dot_pos·=·request_path.find_last_of("."); | 53  | ··std::size_t·last_dot_pos·=·request_path.find_last_of("."); | 
| 55  | ··std::string·extension; | 54  | ··std::string·extension; | 
| 56  | ··if·(last_dot_pos·!=·std::string::npos·&&·last_dot_pos·>·last_slash_pos) | 55  | ··if·(last_dot_pos·!=·std::string::npos·&&·last_dot_pos·>·last_slash_pos) | 
| 57  | ··{ | 56  | ··{ | 
| 58  | ····extension·=·request_path.substr(last_dot_pos·+·1); | 57  | ····extension·=·request_path.substr(last_dot_pos·+·1); | 
| 59  | ··} | 58  | ··} | 
| 60  |  | 59  |  | 
| 61  | ··//·Open·the·file·to·send·back. | 60  | ··//·Open·the·file·to·send·back. | 
| 62  | ··std::string·full_path·=·doc_root_·+·request_path; | 61  | ··std::string·full_path·=·doc_root_·+·request_path; | 
| 63  | ··std::ifstream·is(full_path.c_str(),·std::ios::in·|·std::ios::binary); | 62  | ··std::ifstream·is(full_path.c_str(),·std::ios::in·|·std::ios::binary); | 
| 64  | ··if·(!is) | 63  | ··if·(!is) | 
| 65  | ··{ | 64  | ··{ | 
| 66  | ····rep·=·reply::stock_reply(reply::not_found); | 65  | ····rep·=·reply::stock_reply(reply::not_found); | 
| 67  | ····return; | 66  | ····return; | 
| 68  | ··} | 67  | ··} | 
| 69  |  | 68  |  | 
| 70  | ··//·Fill·out·the·reply·to·be·sent·to·the·client. | 69  | ··//·Fill·out·the·reply·to·be·sent·to·the·client. | 
| 71  | ··rep.status·=·reply::ok; | 70  | ··rep.status·=·reply::ok; | 
| 72  | ··char·buf[512]; | 71  | ··char·buf[512]; | 
| 73  | ··while·(is.read(buf,·sizeof(buf)).gcount()·>·0) | 72  | ··while·(is.read(buf,·sizeof(buf)).gcount()·>·0) | 
| 74  | ····rep.content.append(buf,·is.gcount()); | 73  | ····rep.content.append(buf,·is.gcount()); | 
| 75  | ··rep.headers.resize(2); | 74  | ··rep.headers.resize(2); | 
| 76  | ··rep.headers[0].name·=·"Content-Length"; | 75  | ··rep.headers[0].name·=·"Content-Length"; | 
| 77  | ··rep.headers[0].value·=·boost::lexical_cast<std::string>(rep.content.size()); | 76  | ··rep.headers[0].value·=·std::to_string(rep.content.size()); | 
| 78  | ··rep.headers[1].name·=·"Content-Type"; | 77  | ··rep.headers[1].name·=·"Content-Type"; | 
| 79  | ··rep.headers[1].value·=·mime_types::extension_to_type(extension); | 78  | ··rep.headers[1].value·=·mime_types::extension_to_type(extension); | 
| 80  | } | 79  | } | 
| 81  |  | 80  |  | 
| 82  | bool·request_handler::url_decode(const·std::string&·in,·std::string&·out) | 81  | bool·request_handler::url_decode(const·std::string&·in,·std::string&·out) | 
| 83  | { | 82  | { | 
| 84  | ··out.clear(); | 83  | ··out.clear(); | 
| 85  | ··out.reserve(in.size()); | 84  | ··out.reserve(in.size()); | 
| 86  | ··for·(std::size_t·i·=·0;·i·<·in.size();·++i) | 85  | ··for·(std::size_t·i·=·0;·i·<·in.size();·++i) | 
| 87  | ··{ | 86  | ··{ | 
| 88  | ····if·(in[i]·==·'%') | 87  | ····if·(in[i]·==·'%') | 
| 89  | ····{ | 88  | ····{ | 
| 90  | ······if·(i·+·3·<=·in.size()) | 89  | ······if·(i·+·3·<=·in.size()) | 
| 91  | ······{ | 90  | ······{ | 
| 92  | ········int·value·=·0; | 91  | ········int·value·=·0; | 
| 93  | ········std::istringstream·is(in.substr(i·+·1,·2)); | 92  | ········std::istringstream·is(in.substr(i·+·1,·2)); | 
| 94  | ········if·(is·>>·std::hex·>>·value) | 93  | ········if·(is·>>·std::hex·>>·value) | 
| 95  | ········{ | 94  | ········{ | 
| 96  | ··········out·+=·static_cast<char>(value); | 95  | ··········out·+=·static_cast<char>(value); | 
| 97  | ··········i·+=·2; | 96  | ··········i·+=·2; | 
| 98  | ········} | 97  | ········} | 
| 99  | ········else | 98  | ········else | 
| 100  | ········{ | 99  | ········{ | 
| 101  | ··········return·false; | 100  | ··········return·false; | 
| 102  | ········} | 101  | ········} | 
| 103  | ······} | 102  | ······} | 
| 104  | ······else | 103  | ······else | 
| 105  | ······{ | 104  | ······{ | 
| 106  | ········return·false; | 105  | ········return·false; | 
| 107  | ······} | 106  | ······} | 
| 108  | ····} | 107  | ····} | 
| 109  | ····else·if·(in[i]·==·'+') | 108  | ····else·if·(in[i]·==·'+') | 
| 110  | ····{ | 109  | ····{ | 
| 111  | ······out·+=·'·'; | 110  | ······out·+=·'·'; | 
| 112  | ····} | 111  | ····} | 
| 113  | ····else | 112  | ····else | 
| 114  | ····{ | 113  | ····{ | 
| 115  | ······out·+=·in[i]; | 114  | ······out·+=·in[i]; | 
| 116  | ····} | 115  | ····} | 
| 117  | ··} | 116  | ··} | 
| 118  | ··return·true; | 117  | ··return·true; | 
| 119  | } | 118  | } | 
| 120  |  | 119  |  | 
| 121  | }·//·namespace·server | 120  | }·//·namespace·server | 
| 122  | }·//·namespace·http | 121  | }·//·namespace·http |