diff options
Diffstat (limited to 'response.cpp')
-rw-r--r-- | response.cpp | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/response.cpp b/response.cpp new file mode 100644 index 0000000..78368f6 --- /dev/null +++ b/response.cpp @@ -0,0 +1,92 @@ +#include "response.h" +#include "file.h" + +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; +} + +std::string generate_response(http::request<http::string_body>& req, const Config& config, const Socket& socket) +{ + // 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(config.DocRoot(socket, 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; +} + |