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