1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include "response.h"
#include "file.h"
#include <functional>
using namespace std::placeholders;
namespace {
// Append an HTTP rel-path to a local filesystem path.
// The returned path is normalized for the platform.
std::string
path_cat(
beast::string_view base,
beast::string_view path)
{
if(base.empty())
return std::string(path);
std::string result(base);
#ifdef BOOST_MSVC
char constexpr path_separator = '\\';
if(result.back() == path_separator)
result.resize(result.size() - 1);
result.append(path.data(), path.size());
for(auto& c : result)
if(c == '/')
c = path_separator;
#else
char constexpr path_separator = '/';
if(result.back() == path_separator)
result.resize(result.size() - 1);
result.append(path.data(), path.size());
#endif
return result;
}
}
http_exception::http_exception(std::string message): m_message(message)
{
}
const char* http_exception::what() const noexcept
{
return m_message.data();
}
bad_request_exception::bad_request_exception(std::string message): http_exception(message)
{
}
not_found_exception::not_found_exception(std::string message): http_exception(message)
{
}
server_error_exception::server_error_exception(std::string message): http_exception(message)
{
}
std::string extend_index_html(std::string path)
{
if (path.size() && path.back() == '/')
path.append("index.html");
return path;
}
namespace {
std::string GetServerParam(const std::string& key, Server& server)
{
return "";
}
std::string GetRequestParam(const std::string& key, http::request<http::string_body>& req)
{
return "";
}
void SetResponseHeader(const std::string& key, const std::string& value)
{
}
}
std::string generate_response(http::request<http::string_body>& req, http::response<http::string_body>& res, Server& server)
{
#if 0
std::string host{req["host"]}; // TODO: just use string_view
std::string target{req.target()};
std::string plugin_name { server.GetConfig().GetPlugin(server.GetSocket(), host, target)};
plugin_type plugin{server.GetPlugin(plugin_name)};
auto GetServerParamFunction {std::function<std::string(const std::string& key)>(std::bind(GetServerParam, _1, std::ref(server)))};
auto GetRequestParamFunction {std::function<std::string(const std::string& key)>(std::bind(GetRequestParam, _1, req))};
auto SetResponseHeaderFunction{std::function<void(const std::string& key, const std::string& value)>(SetResponseHeader)};
return plugin->generate_page(GetServerParamFunction, GetRequestParamFunction, SetResponseHeaderFunction);
#else
// Make sure we can handle the method
if( req.method() != http::verb::get &&
req.method() != http::verb::head)
throw bad_request_exception("Unknown HTTP-method");
// Request path must be absolute and not contain "..".
if( req.target().empty() ||
req.target()[0] != '/' ||
req.target().find("..") != beast::string_view::npos)
throw bad_request_exception("Illegal request-target");
// Build the path to the requested file
std::string host{req["host"]}; // TODO: just use string_view
std::string target{req.target()};
std::string path = path_cat(server.GetConfig().DocRoot(server.GetSocket(), host, target), extend_index_html(std::string(req.target())));
std::string result;
try {
result = File::getFile(path);
} catch (const std::runtime_error& ex) {
throw not_found_exception(std::string(req.target()));
} catch (const std::exception& ex) {
throw server_error_exception(ex.what());
}
return result;
#endif
}
|