김민수

application/json 대응,

GET, POST, DELETE 대응.
HTTP CODE 명시
가능한 경우 1글자 string을 char로 변환.
......@@ -36,7 +36,7 @@
bool RemoveProtocolFromUrl(std::string const& url, std::string& protocol, std::string& rest) {
TraceFunc("RemoveProtocolFromUrl");
Trace(std::string("url='")+url+"'");
std::string::size_type pos_colon = url.find(":");
const std::string::size_type pos_colon = url.find(':');
if (pos_colon == std::string::npos) {
rest = url;
......@@ -79,7 +79,7 @@ void SplitGetReq(std::string get_req, std::string& path, std::map<std::string, s
}
}
std::string::size_type qm = get_req.find("?");
const std::string::size_type qm = get_req.find('?');
if (qm != std::string::npos) {
std::string url_params = get_req.substr(qm+1);
......@@ -89,26 +89,26 @@ void SplitGetReq(std::string get_req, std::string& path, std::map<std::string, s
// It makes it easier to split the url for name value pairs, he he he
url_params += "&";
std::string::size_type next_amp = url_params.find("&");
std::string::size_type next_amp = url_params.find('&');
while (next_amp != std::string::npos) {
std::string name_value = url_params.substr(0,next_amp);
url_params = url_params.substr(next_amp+1);
next_amp = url_params.find("&");
next_amp = url_params.find('&');
std::string::size_type pos_equal = name_value.find("=");
const std::string::size_type pos_equal = name_value.find('=');
std::string nam = name_value.substr(0,pos_equal);
std::string val = name_value.substr(pos_equal+1);
std::string::size_type pos_plus;
while ( (pos_plus = val.find("+")) != std::string::npos ) {
while ( (pos_plus = val.find('+')) != std::string::npos ) {
val.replace(pos_plus, 1, " ");
}
// Replacing %xy notation
std::string::size_type pos_hex = 0;
while ( (pos_hex = val.find("%", pos_hex)) != std::string::npos ) {
while ( (pos_hex = val.find('%', pos_hex)) != std::string::npos ) {
std::stringstream h;
h << val.substr(pos_hex+1, 2);
h << std::hex;
......@@ -138,7 +138,7 @@ void SplitUrl(std::string const& url, std::string& protocol, std::string& server
RemoveProtocolFromUrl(url, protocol, server);
if (protocol == "http") {
std::string::size_type pos_slash = server.find("/");
const std::string::size_type pos_slash = server.find('/');
if (pos_slash != std::string::npos) {
Trace("slash found");
......
<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">
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nyffenegger/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ren_00E9/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
\ No newline at end of file

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28010.2003
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Web", "Web\Web.vcxproj", "{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Debug|x64.ActiveCfg = Debug|x64
{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Debug|x64.Build.0 = Debug|x64
{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Debug|x86.ActiveCfg = Debug|Win32
{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Debug|x86.Build.0 = Debug|Win32
{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Release|x64.ActiveCfg = Release|x64
{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Release|x64.Build.0 = Release|x64
{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Release|x86.ActiveCfg = Release|Win32
{C5BB1A73-D2D1-4ECA-A57E-9FB64796750E}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {634C2117-66CB-4787-A0DB-0B4C39468EBB}
EndGlobalSection
EndGlobal
std::string title;
std::string body;
std::string bgcolor="#ffffff";
std::string links =
"<p><a href='/red'>red</a> "
"<br><a href='/blue'>blue</a> "
"<br><a href='/form'>form</a> "
"<br><a href='/auth'>authentication example</a> [use <b>rene</b> as username and <b>secretGarden</b> as password"
"<br><a href='/header'>show some HTTP header details</a> "
;
if(r->path_ == "/") {
title = "Web Server Example";
body = "<h1>Welcome to Rene's Web Server</h1>"
"I wonder what you're going to click" + links;
}
else if (r->path_ == "/red") {
bgcolor = "#ff4444";
title = "You chose red";
body = "<h1>Red</h1>" + links;
}
else if (r->path_ == "/blue") {
bgcolor = "#4444ff";
title = "You chose blue";
body = "<h1>Blue</h1>" + links;
}
else if (r->path_ == "/form") {
title = "Fill a form";
body = "<h1>Fill a form</h1>";
body += "<form action='/form'>"
"<table>"
"<tr><td>Field 1</td><td><input name=field_1></td></tr>"
"<tr><td>Field 2</td><td><input name=field_2></td></tr>"
"<tr><td>Field 3</td><td><input name=field_3></td></tr>"
"</table>"
"<input type=submit></form>";
for (std::map<std::string, std::string>::const_iterator i = r->params_.begin();
i != r->params_.end();
i++) {
body += "<br>" + urlDecode( i->first) + " = " + i->second;
}
body += "<hr>" + links;
}
else if (r->path_ == "/auth") {
if (r->authentication_given_) {
if (r->username_ == "rene" && r->password_ == "secretGarden") {
body = "<h1>Successfully authenticated</h1>" + links;
}
else {
body = "<h1>Wrong username or password</h1>" + links;
r->auth_realm_ = "Private Stuff";
}
}
else {
r->auth_realm_ = "Private Stuff";
}
}
else if (r->path_ == "/header") {
title = "some HTTP header details";
body = std::string ("<table>") +
"<tr><td>Accept:</td><td>" + r->accept_ + "</td></tr>" +
"<tr><td>Accept-Encoding:</td><td>" + r->accept_encoding_ + "</td></tr>" +
"<tr><td>Accept-Language:</td><td>" + r->accept_language_ + "</td></tr>" +
"<tr><td>User-Agent:</td><td>" + r->user_agent_ + "</td></tr>" +
"</table>" +
links;
}
else {
r->status_ = "404 Not Found";
title = "Wrong URL";
body = "<h1>Wrong URL</h1>";
body += "Path is : &gt;" + r->path_ + "&lt;";
}
r->answer_ = "<html><head><title>";
r->answer_ += title;
r->answer_ += "</title></head><body bgcolor='" + bgcolor + "'>";
r->answer_ += body;
r->answer_ += "</body></html>";
r->content_type_ = "text/html";
\ No newline at end of file
#include "webserver.h"
#include "socket/src/Socket.h"
#include "nlohmann/json.hpp"
#include <sstream>
std::string urlDecode(std::string const &eString) {
std::string urlDecode(std::string const &e_string) {
std::string ret;
int j;
for (int i = 0; i < int(eString.length()); i++) {
if (int(eString[i]) == 37) {
sscanf_s(eString.substr(i + 1, 2).c_str(), "%x", &j);
for (int i = 0; i < int(e_string.length()); i++) {
if (int(e_string[i]) == 37) {
sscanf_s(e_string.substr(i + 1, 2).c_str(), "%x", &j);
const auto ch = static_cast<char>(j);
ret += ch;
i = i + 2;
}
else {
ret += eString[i];
ret += e_string[i];
}
}
return (ret);
......@@ -21,94 +24,124 @@ std::string urlDecode(std::string const &eString) {
void Request_Handler(webserver::http_request* r) {
Socket s = *(r->s_);
std::string title;
std::string body;
std::string bgcolor="#ffffff";
std::string links =
"<p><a href='/red'>red</a> "
"<br><a href='/blue'>blue</a> "
"<br><a href='/form'>form</a> "
"<br><a href='/auth'>authentication example</a> [use <b>rene</b> as username and <b>secretGarden</b> as password"
"<br><a href='/header'>show some HTTP header details</a> "
;
if(r->path_ == "/") {
title = "Web Server Example";
body = "<h1>Welcome to Rene's Web Server</h1>"
"I wonder what you're going to click" + links;
}
else if (r->path_ == "/red") {
bgcolor = "#ff4444";
title = "You chose red";
body = "<h1>Red</h1>" + links;
}
else if (r->path_ == "/blue") {
bgcolor = "#4444ff";
title = "You chose blue";
body = "<h1>Blue</h1>" + links;
}
else if (r->path_ == "/form") {
title = "Fill a form";
body = "<h1>Fill a form</h1>";
body += "<form action='/form'>"
"<table>"
"<tr><td>Field 1</td><td><input name=field_1></td></tr>"
"<tr><td>Field 2</td><td><input name=field_2></td></tr>"
"<tr><td>Field 3</td><td><input name=field_3></td></tr>"
"</table>"
"<input type=submit></form>";
for (std::map<std::string, std::string>::const_iterator i = r->params_.begin();
i != r->params_.end();
i++) {
nlohmann::json data;
body += "<br>" + urlDecode( i->first) + " = " + i->second;
r->content_type_ = "application/json";
if(r->path_=="/")
{
r->status_ = "403 Forbidden";
data = { {"type","error"},{"method",r->method_},{"path",r->path_}};
}
body += "<hr>" + links;
else if (r->path_ == "/music")
{
if (r->method_ == "GET") {}
else if (r->method_ == "POST") {}
else if (r->method_ == "DELETE") {}
else
{
r->status_ = "405 Method Not Allowed";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
}
else if (r->path_ == "/auth") {
if (r->authentication_given_) {
if (r->username_ == "rene" && r->password_ == "secretGarden") {
body = "<h1>Successfully authenticated</h1>" + links;
}
else {
body = "<h1>Wrong username or password</h1>" + links;
r->auth_realm_ = "Private Stuff";
else if (r->path_ == "/artist")
{
if (r->method_ == "GET") {}
else if (r->method_ == "POST") {}
else if (r->method_ == "DELETE") {}
else
{
r->status_ = "405 Method Not Allowed";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
}
}
else {
r->auth_realm_ = "Private Stuff";
else if (r->path_ == "/album")
{
if (r->method_ == "GET") {}
else if (r->method_ == "POST") {}
else if (r->method_ == "DELETE") {}
else
{
r->status_ = "405 Method Not Allowed";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
}
}
else if (r->path_ == "/header") {
title = "some HTTP header details";
body = std::string ("<table>") +
"<tr><td>Accept:</td><td>" + r->accept_ + "</td></tr>" +
"<tr><td>Accept-Encoding:</td><td>" + r->accept_encoding_ + "</td></tr>" +
"<tr><td>Accept-Language:</td><td>" + r->accept_language_ + "</td></tr>" +
"<tr><td>User-Agent:</td><td>" + r->user_agent_ + "</td></tr>" +
"</table>" +
links;
else if (r->path_ == "/genre")
{
if (r->method_ == "GET") {}
else if (r->method_ == "POST") {}
else if (r->method_ == "DELETE") {}
else
{
r->status_ = "405 Method Not Allowed";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
}
else {
r->status_ = "404 Not Found";
title = "Wrong URL";
body = "<h1>Wrong URL</h1>";
body += "Path is : &gt;" + r->path_ + "&lt;";
}
else if (r->path_ == "/recent_play")
{
if (r->method_ == "GET") {}
else if (r->method_ == "POST") {}
else if (r->method_ == "DELETE") {}
else
{
r->status_ = "405 Method Not Allowed";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
}
}
else if (r->path_ == "/recent_add")
{
if (r->method_ == "GET") {}
else if (r->method_ == "POST") {}
else if (r->method_ == "DELETE") {}
else
{
r->status_ = "405 Method Not Allowed";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
}
}
else if (r->path_ == "/playlist")
{
if (r->method_ == "GET") {}
else if (r->method_ == "POST") {}
else if (r->method_ == "DELETE") {}
else
{
r->status_ = "405 Method Not Allowed";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };
}
}
else if (r->path_ == "/search")
{
const auto& query = r->params_;
if (r->method_ == "GET")
{
auto type_it=query.find("type");
auto value_it = query.find("value");
if(type_it==r->params_.end()||value_it == r->params_.end())
{
r->status_ = "400 Bad Request";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
}
else
{
r->answer_ = "<html><head><title>";
r->answer_ += title;
r->answer_ += "</title></head><body bgcolor='" + bgcolor + "'>";
r->answer_ += body;
r->answer_ += "</body></html>";
}
}
else
{
r->status_ = "405 Method Not Allowed";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };;
}
}
else{
r->status_ = "404 Not Found";
data = { {"type","error"},{"method",r->method_},{"path",r->path_} };
}
nlohmann::json result = {
{"status", r->status_},
{"data", data}
};
r->answer_ = result.dump();
}
int main() {
......
......@@ -58,15 +58,18 @@ unsigned webserver::Request(Socket* ptr_s) {
else if (line.find("POST") == 0) {
req.method_="POST";
}
else if (line.find("DELETE") == 0) {
req.method_ = "DELETE";
}
std::string path;
std::map<std::string, std::string> params;
const size_t posStartPath = line.find_first_not_of(" ",3);
const size_t posStartPath = line.find_first_not_of(' ',req.method_.length());
SplitGetReq(line.substr(posStartPath), path, params);
req.status_ = "202 OK";
req.status_ = "200 OK";
req.s_ = &s;
req.path_ = path;
req.params_ = params;
......@@ -151,7 +154,7 @@ unsigned webserver::Request(Socket* ptr_s) {
s.SendLine(std::string("Date: ") + asctime_remove_nl + " GMT");
s.SendLine(std::string("Server: ") +serverName);
s.SendLine("Connection: close");
s.SendLine("Content-Type: text/html; charset=UTF-8");
s.SendLine("Content-Type: "+req.content_type_+"; charset=UTF-8");
s.SendLine("Content-Length: " + str_str.str());
s.SendLine("");
s.SendLine(req.answer_);
......
......@@ -57,6 +57,7 @@ class webserver {
no need to additionally set status_ if set */
std::string auth_realm_;
std::string content_type_;
std::string answer_;
/* authentication_given_ is true when the user has entered a username and password.
......