#include "response.h" #include "file.h" #include 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& req) { return ""; } void SetResponseHeader(const std::string& key, const std::string& value) { } } std::string generate_response(http::request& req, http::response& 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::bind(GetServerParam, _1, std::ref(server)))}; auto GetRequestParamFunction {std::function(std::bind(GetRequestParam, _1, req))}; auto SetResponseHeaderFunction{std::function(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 }