김민수

application/json 대응,

GET, POST, DELETE 대응.
HTTP CODE 명시
가능한 경우 1글자 string을 char로 변환.
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
36 bool RemoveProtocolFromUrl(std::string const& url, std::string& protocol, std::string& rest) { 36 bool RemoveProtocolFromUrl(std::string const& url, std::string& protocol, std::string& rest) {
37 TraceFunc("RemoveProtocolFromUrl"); 37 TraceFunc("RemoveProtocolFromUrl");
38 Trace(std::string("url='")+url+"'"); 38 Trace(std::string("url='")+url+"'");
39 - std::string::size_type pos_colon = url.find(":"); 39 + const std::string::size_type pos_colon = url.find(':');
40 40
41 if (pos_colon == std::string::npos) { 41 if (pos_colon == std::string::npos) {
42 rest = url; 42 rest = url;
...@@ -79,7 +79,7 @@ void SplitGetReq(std::string get_req, std::string& path, std::map<std::string, s ...@@ -79,7 +79,7 @@ void SplitGetReq(std::string get_req, std::string& path, std::map<std::string, s
79 } 79 }
80 } 80 }
81 81
82 - std::string::size_type qm = get_req.find("?"); 82 + const std::string::size_type qm = get_req.find('?');
83 if (qm != std::string::npos) { 83 if (qm != std::string::npos) {
84 std::string url_params = get_req.substr(qm+1); 84 std::string url_params = get_req.substr(qm+1);
85 85
...@@ -89,26 +89,26 @@ void SplitGetReq(std::string get_req, std::string& path, std::map<std::string, s ...@@ -89,26 +89,26 @@ void SplitGetReq(std::string get_req, std::string& path, std::map<std::string, s
89 // It makes it easier to split the url for name value pairs, he he he 89 // It makes it easier to split the url for name value pairs, he he he
90 url_params += "&"; 90 url_params += "&";
91 91
92 - std::string::size_type next_amp = url_params.find("&"); 92 + std::string::size_type next_amp = url_params.find('&');
93 93
94 while (next_amp != std::string::npos) { 94 while (next_amp != std::string::npos) {
95 std::string name_value = url_params.substr(0,next_amp); 95 std::string name_value = url_params.substr(0,next_amp);
96 url_params = url_params.substr(next_amp+1); 96 url_params = url_params.substr(next_amp+1);
97 - next_amp = url_params.find("&"); 97 + next_amp = url_params.find('&');
98 98
99 - std::string::size_type pos_equal = name_value.find("="); 99 + const std::string::size_type pos_equal = name_value.find('=');
100 100
101 std::string nam = name_value.substr(0,pos_equal); 101 std::string nam = name_value.substr(0,pos_equal);
102 std::string val = name_value.substr(pos_equal+1); 102 std::string val = name_value.substr(pos_equal+1);
103 103
104 std::string::size_type pos_plus; 104 std::string::size_type pos_plus;
105 - while ( (pos_plus = val.find("+")) != std::string::npos ) { 105 + while ( (pos_plus = val.find('+')) != std::string::npos ) {
106 val.replace(pos_plus, 1, " "); 106 val.replace(pos_plus, 1, " ");
107 } 107 }
108 108
109 // Replacing %xy notation 109 // Replacing %xy notation
110 std::string::size_type pos_hex = 0; 110 std::string::size_type pos_hex = 0;
111 - while ( (pos_hex = val.find("%", pos_hex)) != std::string::npos ) { 111 + while ( (pos_hex = val.find('%', pos_hex)) != std::string::npos ) {
112 std::stringstream h; 112 std::stringstream h;
113 h << val.substr(pos_hex+1, 2); 113 h << val.substr(pos_hex+1, 2);
114 h << std::hex; 114 h << std::hex;
...@@ -138,7 +138,7 @@ void SplitUrl(std::string const& url, std::string& protocol, std::string& server ...@@ -138,7 +138,7 @@ void SplitUrl(std::string const& url, std::string& protocol, std::string& server
138 RemoveProtocolFromUrl(url, protocol, server); 138 RemoveProtocolFromUrl(url, protocol, server);
139 139
140 if (protocol == "http") { 140 if (protocol == "http") {
141 - std::string::size_type pos_slash = server.find("/"); 141 + const std::string::size_type pos_slash = server.find('/');
142 142
143 if (pos_slash != std::string::npos) { 143 if (pos_slash != std::string::npos) {
144 Trace("slash found"); 144 Trace("slash found");
......
1 +<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2 + <s:Boolean x:Key="/Default/UserDictionary/Words/=Nyffenegger/@EntryIndexedValue">True</s:Boolean>
3 + <s:Boolean x:Key="/Default/UserDictionary/Words/=Ren_00E9/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
...\ No newline at end of file ...\ No newline at end of file
1 +
2 +Microsoft Visual Studio Solution File, Format Version 12.00
3 +# Visual Studio 15
4 +VisualStudioVersion = 15.0.28010.2003
5 +MinimumVisualStudioVersion = 10.0.40219.1
6 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Web", "Web\Web.vcxproj", "{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}"
7 +EndProject
8 +Global
9 + GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 + Debug|x64 = Debug|x64
11 + Debug|x86 = Debug|x86
12 + Release|x64 = Release|x64
13 + Release|x86 = Release|x86
14 + EndGlobalSection
15 + GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 + {C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Debug|x64.ActiveCfg = Debug|x64
17 + {C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Debug|x64.Build.0 = Debug|x64
18 + {C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Debug|x86.ActiveCfg = Debug|Win32
19 + {C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Debug|x86.Build.0 = Debug|Win32
20 + {C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Release|x64.ActiveCfg = Release|x64
21 + {C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Release|x64.Build.0 = Release|x64
22 + {C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Release|x86.ActiveCfg = Release|Win32
23 + {C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Release|x86.Build.0 = Release|Win32
24 + EndGlobalSection
25 + GlobalSection(SolutionProperties) = preSolution
26 + HideSolutionNode = FALSE
27 + EndGlobalSection
28 + GlobalSection(ExtensibilityGlobals) = postSolution
29 + SolutionGuid = {634C2117-66CB-4787-A0DB-0B4C39468EBB}
30 + EndGlobalSection
31 +EndGlobal
1 +std::string title;
2 + std::string body;
3 + std::string bgcolor="#ffffff";
4 + std::string links =
5 + "<p><a href='/red'>red</a> "
6 + "<br><a href='/blue'>blue</a> "
7 + "<br><a href='/form'>form</a> "
8 + "<br><a href='/auth'>authentication example</a> [use <b>rene</b> as username and <b>secretGarden</b> as password"
9 + "<br><a href='/header'>show some HTTP header details</a> "
10 + ;
11 +
12 + if(r->path_ == "/") {
13 + title = "Web Server Example";
14 + body = "<h1>Welcome to Rene's Web Server</h1>"
15 + "I wonder what you're going to click" + links;
16 + }
17 + else if (r->path_ == "/red") {
18 + bgcolor = "#ff4444";
19 + title = "You chose red";
20 + body = "<h1>Red</h1>" + links;
21 + }
22 + else if (r->path_ == "/blue") {
23 + bgcolor = "#4444ff";
24 + title = "You chose blue";
25 + body = "<h1>Blue</h1>" + links;
26 + }
27 + else if (r->path_ == "/form") {
28 + title = "Fill a form";
29 +
30 + body = "<h1>Fill a form</h1>";
31 + body += "<form action='/form'>"
32 + "<table>"
33 + "<tr><td>Field 1</td><td><input name=field_1></td></tr>"
34 + "<tr><td>Field 2</td><td><input name=field_2></td></tr>"
35 + "<tr><td>Field 3</td><td><input name=field_3></td></tr>"
36 + "</table>"
37 + "<input type=submit></form>";
38 +
39 +
40 + for (std::map<std::string, std::string>::const_iterator i = r->params_.begin();
41 + i != r->params_.end();
42 + i++) {
43 +
44 +
45 + body += "<br>" + urlDecode( i->first) + " = " + i->second;
46 + }
47 +
48 +
49 + body += "<hr>" + links;
50 +
51 + }
52 + else if (r->path_ == "/auth") {
53 + if (r->authentication_given_) {
54 + if (r->username_ == "rene" && r->password_ == "secretGarden") {
55 + body = "<h1>Successfully authenticated</h1>" + links;
56 + }
57 + else {
58 + body = "<h1>Wrong username or password</h1>" + links;
59 + r->auth_realm_ = "Private Stuff";
60 + }
61 + }
62 + else {
63 + r->auth_realm_ = "Private Stuff";
64 + }
65 + }
66 + else if (r->path_ == "/header") {
67 + title = "some HTTP header details";
68 + body = std::string ("<table>") +
69 + "<tr><td>Accept:</td><td>" + r->accept_ + "</td></tr>" +
70 + "<tr><td>Accept-Encoding:</td><td>" + r->accept_encoding_ + "</td></tr>" +
71 + "<tr><td>Accept-Language:</td><td>" + r->accept_language_ + "</td></tr>" +
72 + "<tr><td>User-Agent:</td><td>" + r->user_agent_ + "</td></tr>" +
73 + "</table>" +
74 + links;
75 + }
76 + else {
77 + r->status_ = "404 Not Found";
78 + title = "Wrong URL";
79 + body = "<h1>Wrong URL</h1>";
80 + body += "Path is : &gt;" + r->path_ + "&lt;";
81 + }
82 +
83 + r->answer_ = "<html><head><title>";
84 + r->answer_ += title;
85 + r->answer_ += "</title></head><body bgcolor='" + bgcolor + "'>";
86 + r->answer_ += body;
87 + r->answer_ += "</body></html>";
88 + r->content_type_ = "text/html";
...\ No newline at end of file ...\ No newline at end of file
1 #include "webserver.h" 1 #include "webserver.h"
2 #include "socket/src/Socket.h" 2 #include "socket/src/Socket.h"
3 #include "nlohmann/json.hpp" 3 #include "nlohmann/json.hpp"
4 +#include <sstream>
4 5
5 -std::string urlDecode(std::string const &eString) { 6 +
7 +
8 +std::string urlDecode(std::string const &e_string) {
6 std::string ret; 9 std::string ret;
7 int j; 10 int j;
8 - for (int i = 0; i < int(eString.length()); i++) { 11 + for (int i = 0; i < int(e_string.length()); i++) {
9 - if (int(eString[i]) == 37) { 12 + if (int(e_string[i]) == 37) {
10 - sscanf_s(eString.substr(i + 1, 2).c_str(), "%x", &j); 13 + sscanf_s(e_string.substr(i + 1, 2).c_str(), "%x", &j);
11 const auto ch = static_cast<char>(j); 14 const auto ch = static_cast<char>(j);
12 ret += ch; 15 ret += ch;
13 i = i + 2; 16 i = i + 2;
14 } 17 }
15 else { 18 else {
16 - ret += eString[i]; 19 + ret += e_string[i];
17 } 20 }
18 } 21 }
19 return (ret); 22 return (ret);
...@@ -21,94 +24,124 @@ std::string urlDecode(std::string const &eString) { ...@@ -21,94 +24,124 @@ std::string urlDecode(std::string const &eString) {
21 24
22 void Request_Handler(webserver::http_request* r) { 25 void Request_Handler(webserver::http_request* r) {
23 Socket s = *(r->s_); 26 Socket s = *(r->s_);
27 + nlohmann::json data;
24 28
25 - std::string title;
26 - std::string body;
27 - std::string bgcolor="#ffffff";
28 - std::string links =
29 - "<p><a href='/red'>red</a> "
30 - "<br><a href='/blue'>blue</a> "
31 - "<br><a href='/form'>form</a> "
32 - "<br><a href='/auth'>authentication example</a> [use <b>rene</b> as username and <b>secretGarden</b> as password"
33 - "<br><a href='/header'>show some HTTP header details</a> "
34 - ;
35 29
36 - if(r->path_ == "/") { 30 + r->content_type_ = "application/json";
37 - title = "Web Server Example"; 31 + if(r->path_=="/")
38 - body = "<h1>Welcome to Rene's Web Server</h1>" 32 + {
39 - "I wonder what you're going to click" + links; 33 + r->status_ = "403 Forbidden";
34 + data = { {"type","error"},{"method",r->method_},{"path",r->path_}};
40 } 35 }
41 - else if (r->path_ == "/red") { 36 + else if (r->path_ == "/music")
42 - bgcolor = "#ff4444"; 37 + {
43 - title = "You chose red"; 38 + if (r->method_ == "GET") {}
44 - body = "<h1>Red</h1>" + links; 39 + else if (r->method_ == "POST") {}
40 + else if (r->method_ == "DELETE") {}
41 + else
42 + {
43 + r->status_ = "405 Method Not Allowed";
44 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
45 + }
45 } 46 }
46 - else if (r->path_ == "/blue") { 47 + else if (r->path_ == "/artist")
47 - bgcolor = "#4444ff"; 48 + {
48 - title = "You chose blue"; 49 + if (r->method_ == "GET") {}
49 - body = "<h1>Blue</h1>" + links; 50 + else if (r->method_ == "POST") {}
51 + else if (r->method_ == "DELETE") {}
52 + else
53 + {
54 + r->status_ = "405 Method Not Allowed";
55 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
56 + }
50 } 57 }
51 - else if (r->path_ == "/form") { 58 + else if (r->path_ == "/album")
52 - title = "Fill a form"; 59 + {
53 - 60 + if (r->method_ == "GET") {}
54 - body = "<h1>Fill a form</h1>"; 61 + else if (r->method_ == "POST") {}
55 - body += "<form action='/form'>" 62 + else if (r->method_ == "DELETE") {}
56 - "<table>" 63 + else
57 - "<tr><td>Field 1</td><td><input name=field_1></td></tr>" 64 + {
58 - "<tr><td>Field 2</td><td><input name=field_2></td></tr>" 65 + r->status_ = "405 Method Not Allowed";
59 - "<tr><td>Field 3</td><td><input name=field_3></td></tr>" 66 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
60 - "</table>" 67 + }
61 - "<input type=submit></form>";
62 -
63 -
64 - for (std::map<std::string, std::string>::const_iterator i = r->params_.begin();
65 - i != r->params_.end();
66 - i++) {
67 -
68 -
69 - body += "<br>" + urlDecode( i->first) + " = " + i->second;
70 - }
71 -
72 -
73 - body += "<hr>" + links;
74 -
75 } 68 }
76 - else if (r->path_ == "/auth") { 69 + else if (r->path_ == "/genre")
77 - if (r->authentication_given_) { 70 + {
78 - if (r->username_ == "rene" && r->password_ == "secretGarden") { 71 + if (r->method_ == "GET") {}
79 - body = "<h1>Successfully authenticated</h1>" + links; 72 + else if (r->method_ == "POST") {}
80 - } 73 + else if (r->method_ == "DELETE") {}
81 - else { 74 + else
82 - body = "<h1>Wrong username or password</h1>" + links; 75 + {
83 - r->auth_realm_ = "Private Stuff"; 76 + r->status_ = "405 Method Not Allowed";
84 - } 77 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
85 - } 78 + }
86 - else {
87 - r->auth_realm_ = "Private Stuff";
88 - }
89 } 79 }
90 - else if (r->path_ == "/header") { 80 + else if (r->path_ == "/recent_play")
91 - title = "some HTTP header details"; 81 + {
92 - body = std::string ("<table>") + 82 + if (r->method_ == "GET") {}
93 - "<tr><td>Accept:</td><td>" + r->accept_ + "</td></tr>" + 83 + else if (r->method_ == "POST") {}
94 - "<tr><td>Accept-Encoding:</td><td>" + r->accept_encoding_ + "</td></tr>" + 84 + else if (r->method_ == "DELETE") {}
95 - "<tr><td>Accept-Language:</td><td>" + r->accept_language_ + "</td></tr>" + 85 + else
96 - "<tr><td>User-Agent:</td><td>" + r->user_agent_ + "</td></tr>" + 86 + {
97 - "</table>" + 87 + r->status_ = "405 Method Not Allowed";
98 - links; 88 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
89 + }
99 } 90 }
100 - else { 91 + else if (r->path_ == "/recent_add")
101 - r->status_ = "404 Not Found"; 92 + {
102 - title = "Wrong URL"; 93 + if (r->method_ == "GET") {}
103 - body = "<h1>Wrong URL</h1>"; 94 + else if (r->method_ == "POST") {}
104 - body += "Path is : &gt;" + r->path_ + "&lt;"; 95 + else if (r->method_ == "DELETE") {}
96 + else
97 + {
98 + r->status_ = "405 Method Not Allowed";
99 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
100 + }
105 } 101 }
106 - 102 + else if (r->path_ == "/playlist")
107 - r->answer_ = "<html><head><title>"; 103 + {
108 - r->answer_ += title; 104 + if (r->method_ == "GET") {}
109 - r->answer_ += "</title></head><body bgcolor='" + bgcolor + "'>"; 105 + else if (r->method_ == "POST") {}
110 - r->answer_ += body; 106 + else if (r->method_ == "DELETE") {}
111 - r->answer_ += "</body></html>"; 107 + else
108 + {
109 + r->status_ = "405 Method Not Allowed";
110 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };
111 + }
112 + }
113 + else if (r->path_ == "/search")
114 + {
115 + const auto& query = r->params_;
116 + if (r->method_ == "GET")
117 + {
118 + auto type_it=query.find("type");
119 + auto value_it = query.find("value");
120 + if(type_it==r->params_.end()||value_it == r->params_.end())
121 + {
122 + r->status_ = "400 Bad Request";
123 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
124 + }
125 + else
126 + {
127 +
128 + }
129 + }
130 + else
131 + {
132 + r->status_ = "405 Method Not Allowed";
133 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
134 + }
135 + }
136 + else{
137 + r->status_ = "404 Not Found";
138 + data = { {"type","error"},{"method",r->method_},{"path",r->path_} };
139 + }
140 + nlohmann::json result = {
141 + {"status", r->status_},
142 + {"data", data}
143 + };
144 + r->answer_ = result.dump();
112 } 145 }
113 146
114 int main() { 147 int main() {
......
...@@ -58,15 +58,18 @@ unsigned webserver::Request(Socket* ptr_s) { ...@@ -58,15 +58,18 @@ unsigned webserver::Request(Socket* ptr_s) {
58 else if (line.find("POST") == 0) { 58 else if (line.find("POST") == 0) {
59 req.method_="POST"; 59 req.method_="POST";
60 } 60 }
61 + else if (line.find("DELETE") == 0) {
62 + req.method_ = "DELETE";
63 + }
61 64
62 std::string path; 65 std::string path;
63 std::map<std::string, std::string> params; 66 std::map<std::string, std::string> params;
64 67
65 - const size_t posStartPath = line.find_first_not_of(" ",3); 68 + const size_t posStartPath = line.find_first_not_of(' ',req.method_.length());
66 69
67 SplitGetReq(line.substr(posStartPath), path, params); 70 SplitGetReq(line.substr(posStartPath), path, params);
68 71
69 - req.status_ = "202 OK"; 72 + req.status_ = "200 OK";
70 req.s_ = &s; 73 req.s_ = &s;
71 req.path_ = path; 74 req.path_ = path;
72 req.params_ = params; 75 req.params_ = params;
...@@ -151,7 +154,7 @@ unsigned webserver::Request(Socket* ptr_s) { ...@@ -151,7 +154,7 @@ unsigned webserver::Request(Socket* ptr_s) {
151 s.SendLine(std::string("Date: ") + asctime_remove_nl + " GMT"); 154 s.SendLine(std::string("Date: ") + asctime_remove_nl + " GMT");
152 s.SendLine(std::string("Server: ") +serverName); 155 s.SendLine(std::string("Server: ") +serverName);
153 s.SendLine("Connection: close"); 156 s.SendLine("Connection: close");
154 - s.SendLine("Content-Type: text/html; charset=UTF-8"); 157 + s.SendLine("Content-Type: "+req.content_type_+"; charset=UTF-8");
155 s.SendLine("Content-Length: " + str_str.str()); 158 s.SendLine("Content-Length: " + str_str.str());
156 s.SendLine(""); 159 s.SendLine("");
157 s.SendLine(req.answer_); 160 s.SendLine(req.answer_);
......
...@@ -56,7 +56,8 @@ class webserver { ...@@ -56,7 +56,8 @@ class webserver {
56 /* auth_realm_: allows to set the basic realm for an authentication, 56 /* auth_realm_: allows to set the basic realm for an authentication,
57 no need to additionally set status_ if set */ 57 no need to additionally set status_ if set */
58 std::string auth_realm_; 58 std::string auth_realm_;
59 - 59 +
60 + std::string content_type_;
60 std::string answer_; 61 std::string answer_;
61 62
62 /* authentication_given_ is true when the user has entered a username and password. 63 /* authentication_given_ is true when the user has entered a username and password.
......