generated from Sithas/conan_template
Вынесена функция HandleRequest.h
(cherry picked from commit a5542aba7c322dee98a7236b1a5dad70355d179d)
This commit is contained in:
+2
-1
@@ -15,7 +15,8 @@ find_package(Boost REQUIRED)
|
||||
|
||||
add_executable(App ./src/main.cpp
|
||||
./src/helpers/helpers.h
|
||||
./src/helpers/helpers.cpp)
|
||||
./src/helpers/helpers.cpp
|
||||
./src/endpoints_handlers/HandleRequest.h)
|
||||
|
||||
target_link_libraries(App PRIVATE Boost::boost)
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
#include <boost/beast.hpp>
|
||||
|
||||
namespace uad {
|
||||
template <class Body, class Allocator, class Send>
|
||||
void HandleRequest(boost::beast::string_view doc_root,
|
||||
boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator>> &&req,
|
||||
Send &&send) {
|
||||
auto const bad_request = [&req](beast::string_view why) {
|
||||
boost::beast::http::response<boost::beast::http::string_body> res{boost::beast::http::status::bad_request,
|
||||
req.version()};
|
||||
res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(boost::beast::http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = std::string(why);
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
auto const not_found = [&req](beast::string_view target) {
|
||||
boost::beast::http::response<boost::beast::http::string_body> res{boost::beast::http::status::not_found,
|
||||
req.version()};
|
||||
res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(boost::beast::http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = "The resource '" + std::string(target) + "' was not found.";
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
auto const server_error = [&req](beast::string_view what) {
|
||||
boost::beast::http::response<boost::beast::http::string_body> res{boost::beast::http::status::internal_server_error,
|
||||
req.version()};
|
||||
res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(boost::beast::http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = "An error occurred: '" + std::string(what) + "'";
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
if (req.method() != boost::beast::http::verb::get && req.method() != boost::beast::http::verb::head)
|
||||
return send(bad_request("Unknown boost::beast::HTTP-method"));
|
||||
|
||||
if (req.target().empty() || req.target()[0] != '/' ||
|
||||
req.target().find("..") != beast::string_view::npos)
|
||||
return send(bad_request("Illegal request-target"));
|
||||
|
||||
std::string path = PathCat(doc_root, req.target());
|
||||
if (req.target().back() == '/')
|
||||
path.append("index.html");
|
||||
|
||||
beast::error_code ec;
|
||||
boost::beast::http::file_body::value_type body;
|
||||
body.open(path.c_str(), beast::file_mode::scan, ec);
|
||||
|
||||
if (ec == beast::errc::no_such_file_or_directory)
|
||||
return send(not_found(req.target()));
|
||||
|
||||
if (ec)
|
||||
return send(server_error(ec.message()));
|
||||
|
||||
auto const size = body.size();
|
||||
|
||||
if (req.method() == boost::beast::http::verb::head) {
|
||||
boost::beast::http::response<boost::beast::http::empty_body> res{boost::beast::http::status::ok, req.version()};
|
||||
res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(boost::beast::http::field::content_type, MimeType(path));
|
||||
res.content_length(size);
|
||||
res.keep_alive(req.keep_alive());
|
||||
return send(std::move(res));
|
||||
}
|
||||
|
||||
boost::beast::http::response<boost::beast::http::file_body> res{
|
||||
std::piecewise_construct, std::make_tuple(std::move(body)),
|
||||
std::make_tuple(boost::beast::http::status::ok, req.version())};
|
||||
res.set(boost::beast::http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(boost::beast::http::field::content_type, MimeType(path));
|
||||
res.content_length(size);
|
||||
res.keep_alive(req.keep_alive());
|
||||
return send(std::move(res));
|
||||
}
|
||||
}
|
||||
+2
-92
@@ -18,6 +18,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "./helpers/helpers.h"
|
||||
#include "./endpoints_handlers/HandleRequest.h"
|
||||
|
||||
namespace beast = boost::beast;
|
||||
namespace http = beast::http;
|
||||
@@ -26,97 +27,6 @@ namespace net = boost::asio;
|
||||
using tcp = boost::asio::ip::tcp;
|
||||
using namespace uad;
|
||||
|
||||
template <class Body, class Allocator, class Send>
|
||||
void handle_request(beast::string_view doc_root,
|
||||
http::request<Body, http::basic_fields<Allocator>> &&req,
|
||||
Send &&send) {
|
||||
// Returns a bad request response
|
||||
auto const bad_request = [&req](beast::string_view why) {
|
||||
http::response<http::string_body> res{http::status::bad_request,
|
||||
req.version()};
|
||||
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = std::string(why);
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
// Returns a not found response
|
||||
auto const not_found = [&req](beast::string_view target) {
|
||||
http::response<http::string_body> res{http::status::not_found,
|
||||
req.version()};
|
||||
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = "The resource '" + std::string(target) + "' was not found.";
|
||||
res.prepare_payload();
|
||||
return res;
|
||||
};
|
||||
|
||||
// Returns a server error response
|
||||
auto const server_error = [&req](beast::string_view what) {
|
||||
http::response<http::string_body> res{http::status::internal_server_error,
|
||||
req.version()};
|
||||
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, "text/html");
|
||||
res.keep_alive(req.keep_alive());
|
||||
res.body() = "An error occurred: '" + std::string(what) + "'";
|
||||
res.prepare_payload();
|
||||
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 path = PathCat(doc_root, 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, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, MimeType(path));
|
||||
res.content_length(size);
|
||||
res.keep_alive(req.keep_alive());
|
||||
return send(std::move(res));
|
||||
}
|
||||
|
||||
// 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())};
|
||||
res.set(http::field::server, BOOST_BEAST_VERSION_STRING);
|
||||
res.set(http::field::content_type, MimeType(path));
|
||||
res.content_length(size);
|
||||
res.keep_alive(req.keep_alive());
|
||||
return send(std::move(res));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Report a failure
|
||||
@@ -334,7 +244,7 @@ private:
|
||||
}
|
||||
|
||||
// Send the response
|
||||
handle_request(*doc_root_, parser_->release(), queue_);
|
||||
HandleRequest(*doc_root_, parser_->release(), queue_);
|
||||
|
||||
// If we aren't at the queue limit, try to pipeline another request
|
||||
if (!queue_.is_full())
|
||||
|
||||
Reference in New Issue
Block a user