diff options
Diffstat (limited to 'https.cpp')
-rw-r--r-- | https.cpp | 94 |
1 files changed, 16 insertions, 78 deletions
@@ -3,6 +3,7 @@ #include "config.h" #include "file.h" #include "server.h" +#include "response.h" #include <boost/beast/version.hpp> @@ -74,33 +75,6 @@ mime_type(beast::string_view path) return "application/text"; } -// 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; -} - // This function produces an HTTP response for the given // request. The type of the response object depends on the // contents of the request, so the interface requires the @@ -154,60 +128,24 @@ handle_request( return res; }; - // Make sure we can handle the method - if( req.method() != http::verb::get && - req.method() != http::verb::head) - return send(bad_request("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) - return send(bad_request("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), req.target()); - if(req.target().back() == '/') - path.append("index.html"); - - // Attempt to open the file - beast::error_code ec; - http::file_body::value_type body; - body.open(path.c_str(), beast::file_mode::scan, ec); - - // Handle the case where the file doesn't exist - if(ec == beast::errc::no_such_file_or_directory) - return send(not_found(req.target())); - - // Handle an unknown error - if(ec) - return send(server_error(ec.message())); - - // Cache the size since we need it after the move - auto const size = body.size(); - - // Respond to HEAD request - if(req.method() == http::verb::head) - { - http::response<http::empty_body> res{http::status::ok, req.version()}; - res.set(http::field::server, VersionString); - res.set(http::field::content_type, mime_type(path)); - res.content_length(size); - res.keep_alive(req.keep_alive()); - return send(std::move(res)); + std::string res_data; + try { + res_data = generate_response(req, config, socket); + } catch(const bad_request_exception& ex) { + return send(bad_request(ex.what())); + } catch(const not_found_exception& ex) { + return send(not_found(ex.what())); + } catch(const server_error_exception& ex) { + return send(server_error(ex.what())); } - - // Respond to GET request - http::response<http::file_body> res{ - std::piecewise_construct, - std::make_tuple(std::move(body)), - std::make_tuple(http::status::ok, req.version())}; + + http::response<http::string_body> res{http::status::ok, req.version()}; res.set(http::field::server, VersionString); - res.set(http::field::content_type, mime_type(path)); - res.content_length(size); + res.set(http::field::content_type, mime_type(extend_index_html(std::string(req.target())))); + res.content_length(res_data.size()); res.keep_alive(req.keep_alive()); + if (req.method() != http::verb::head) + res.body() = res_data; return send(std::move(res)); } |