diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-04-10 15:36:59 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-04-10 15:36:59 +0200 |
commit | c0ccf16c69d43a89674640c61d13ec2c02b128d6 (patch) | |
tree | ae840bc16f0ddb430bdd68aacef4d7cb2af970d9 /response.cpp | |
parent | 0d157fb407a35f8afe6d6f0f4c2cc5cd5d5a1933 (diff) |
First working plugin: static-files
Diffstat (limited to 'response.cpp')
-rw-r--r-- | response.cpp | 145 |
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 } |