summaryrefslogtreecommitdiffhomepage
path: root/response.cpp
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-04-10 15:36:59 +0200
committerRoland Reichwein <mail@reichwein.it>2020-04-10 15:36:59 +0200
commitc0ccf16c69d43a89674640c61d13ec2c02b128d6 (patch)
treeae840bc16f0ddb430bdd68aacef4d7cb2af970d9 /response.cpp
parent0d157fb407a35f8afe6d6f0f4c2cc5cd5d5a1933 (diff)
First working plugin: static-files
Diffstat (limited to 'response.cpp')
-rw-r--r--response.cpp145
1 files changed, 54 insertions, 91 deletions
diff --git a/response.cpp b/response.cpp
index 507b2d7..6b7ae6a 100644
--- a/response.cpp
+++ b/response.cpp
@@ -2,61 +2,11 @@
#include "file.h"
#include <functional>
+#include <iostream>
+#include <unordered_map>
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() == '/')
@@ -68,61 +18,74 @@ namespace {
std::string GetServerParam(const std::string& key, Server& server)
{
- return "";
+ // following are the supported fields:
+ // ...
+ throw std::runtime_error("Unsupported server param: "s + key);
}
-std::string GetRequestParam(const std::string& key, http::request<http::string_body>& req)
+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)
{
- return "";
+ 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)
+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(http::request<http::string_body>& req, http::response<http::string_body>& res, Server& server)
+std::string generate_response(request_type& req, response_type& res, Server& server)
{
-#if 0
- std::string host{req["host"]}; // TODO: just use string_view
+ 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, req))};
- auto SetResponseHeaderFunction{std::function<void(const std::string& key, const std::string& value)>(SetResponseHeader)};
+ 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);
-
-#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
}