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
|
#include "response.h"
#include "file.h"
#include <functional>
#include <iostream>
#include <unordered_map>
using namespace std::placeholders;
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)
{
// following are the supported fields:
// ...
throw std::runtime_error("Unsupported server param: "s + key);
}
std::unordered_map<std::string, std::function<std::string(request_type&, Server&)>> GetRequestParamFunctions{
// following are the supported fields:
{"target", [](request_type& req, Server& server){return std::string{req.target()};}},
{"rel_target", [](request_type& req, Server& server){
std::string host{req["host"]};
std::string target{req.target()};
return server.GetConfig().GetRelativePath(server.GetSocket(), host, target);
}},
{"doc_root", [](request_type& req, Server& server) {
std::string host{req["host"]};
std::string target{req.target()};
return server.GetConfig().DocRoot(server.GetSocket(), host, target);
}},
{"method", [](request_type& req, Server& server){
if (req.method() == http::verb::get)
return "GET";
else if (req.method() == http::verb::post)
return "POST";
else if (req.method() == http::verb::head)
return "HEAD";
else
return "";
}},
};
std::string GetRequestParam(const std::string& key, request_type& req, Server& server)
{
auto it = GetRequestParamFunctions.find(key);
if (it != GetRequestParamFunctions.end())
return it->second(req, server);
throw std::runtime_error("Unsupported request param: "s + key);
}
void SetResponseHeader(const std::string& key, const std::string& value, response_type& res)
{
// following are the supported fields:
if (key == "status") { // HTTP Status, e.g. "200" (OK)
res.result(unsigned(stoul(value)));
} else if (key == "server") { // Server name/version string
res.set(http::field::server, value);
} else if (key == "content_type") { // e.g. text/html
res.set(http::field::content_type, value);
} else
throw std::runtime_error("Unsupported response field: "s + key);
}
} // anonymous namespace
std::string generate_response(request_type& req, response_type& res, Server& server)
{
std::string host{req["host"]};
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, std::ref(req), std::ref(server)))};
auto SetResponseHeaderFunction{std::function<void(const std::string& key, const std::string& value)>(std::bind(SetResponseHeader, _1, _2, std::ref(res)))};
return plugin->generate_page(GetServerParamFunction, GetRequestParamFunction, SetResponseHeaderFunction);
}
|