src/​examples/​cpp03/​http/​server/​request_handler.​cppsrc/​examples/​cpp11/​http/​server/​request_handler.​cpp
1 /​/​1 /​/​
2 /​/​·​request_handler.​cpp2 /​/​·​request_handler.​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·​accompanying7 /​/​·​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(ext​ension)​;​78 ··​rep.​headers[1].​value·​=·​mime_types:​:​extension_to_type(ext​ension)​;​
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>(val​ue)​;​95 ··········​out·​+=·​static_cast<char>(val​ue)​;​
97 ··········​i·​+=·​2;​96 ··········​i·​+=·​2;​
98 ········​}97 ········​}
99 ········​else98 ········​else
100 ········​{99 ········​{
101 ··········​return·​false;​100 ··········​return·​false;​
102 ········​}101 ········​}
103 ······​}102 ······​}
104 ······​else103 ······​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 ····​else112 ····​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·​server120 }·​/​/​·​namespace·​server
122 }·​/​/​·​namespace·​http121 }·​/​/​·​namespace·​http