mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
Use file_body for valid requests, string_body otherwise.
This commit is contained in:
committed by
Vinnie Falco
parent
783c52b025
commit
8179019590
@ -1,3 +1,9 @@
|
|||||||
|
Version 75:
|
||||||
|
|
||||||
|
* Use file_body for valid requests, string_body otherwise.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Version 74:
|
Version 74:
|
||||||
|
|
||||||
* Add file_stdio and File concept
|
* Add file_stdio and File concept
|
||||||
|
@ -71,11 +71,17 @@ private:
|
|||||||
boost::asio::basic_waitable_timer<std::chrono::steady_clock> request_deadline_{
|
boost::asio::basic_waitable_timer<std::chrono::steady_clock> request_deadline_{
|
||||||
acceptor_.get_io_service(), (std::chrono::steady_clock::time_point::max)()};
|
acceptor_.get_io_service(), (std::chrono::steady_clock::time_point::max)()};
|
||||||
|
|
||||||
// The response message.
|
// The string-based response message.
|
||||||
boost::optional<http::response<http::string_body, http::basic_fields<alloc_t>>> response_;
|
boost::optional<http::response<http::string_body, http::basic_fields<alloc_t>>> string_response_;
|
||||||
|
|
||||||
// The response serializer.
|
// The string-based response serializer.
|
||||||
boost::optional<http::response_serializer<http::string_body, http::basic_fields<alloc_t>>> serializer_;
|
boost::optional<http::response_serializer<http::string_body, http::basic_fields<alloc_t>>> string_serializer_;
|
||||||
|
|
||||||
|
// The file-based response message.
|
||||||
|
boost::optional<http::response<http::file_body, http::basic_fields<alloc_t>>> file_response_;
|
||||||
|
|
||||||
|
// The file-based response serializer.
|
||||||
|
boost::optional<http::response_serializer<http::file_body, http::basic_fields<alloc_t>>> file_serializer_;
|
||||||
|
|
||||||
void accept()
|
void accept()
|
||||||
{
|
{
|
||||||
@ -136,77 +142,104 @@ private:
|
|||||||
|
|
||||||
void process_request(http::request<request_body_t, http::basic_fields<alloc_t>> const& req)
|
void process_request(http::request<request_body_t, http::basic_fields<alloc_t>> const& req)
|
||||||
{
|
{
|
||||||
response_.emplace(
|
|
||||||
std::piecewise_construct,
|
|
||||||
std::make_tuple(),
|
|
||||||
std::make_tuple(alloc_));
|
|
||||||
|
|
||||||
response_->set(http::field::connection, "close");
|
|
||||||
|
|
||||||
switch (req.method())
|
switch (req.method())
|
||||||
{
|
{
|
||||||
case http::verb::get:
|
case http::verb::get:
|
||||||
response_->result(http::status::ok);
|
send_file(req.target());
|
||||||
response_->set(http::field::server, "Beast");
|
|
||||||
load_file(req.target());
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// We return responses indicating an error if
|
// We return responses indicating an error if
|
||||||
// we do not recognize the request method.
|
// we do not recognize the request method.
|
||||||
response_->result(http::status::bad_request);
|
send_bad_response(
|
||||||
response_->set(http::field::content_type, "text/plain");
|
http::status::bad_request,
|
||||||
response_->body = "Invalid request-method '" + req.method_string().to_string() + "'";
|
"Invalid request-method '" + req.method_string().to_string() + "'\r\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
write_response();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void load_file(beast::string_view target)
|
void send_bad_response(
|
||||||
|
http::status status,
|
||||||
|
std::string const& error)
|
||||||
|
{
|
||||||
|
string_response_.emplace(
|
||||||
|
std::piecewise_construct,
|
||||||
|
std::make_tuple(),
|
||||||
|
std::make_tuple(alloc_));
|
||||||
|
|
||||||
|
string_response_->result(status);
|
||||||
|
string_response_->set(http::field::server, "Beast");
|
||||||
|
string_response_->set(http::field::connection, "close");
|
||||||
|
string_response_->set(http::field::content_type, "text/plain");
|
||||||
|
string_response_->body = error;
|
||||||
|
string_response_->prepare_payload();
|
||||||
|
|
||||||
|
string_serializer_.emplace(*string_response_);
|
||||||
|
|
||||||
|
http::async_write(
|
||||||
|
socket_,
|
||||||
|
*string_serializer_,
|
||||||
|
[this](beast::error_code ec)
|
||||||
|
{
|
||||||
|
socket_.shutdown(tcp::socket::shutdown_send, ec);
|
||||||
|
string_serializer_.reset();
|
||||||
|
string_response_.reset();
|
||||||
|
accept();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_file(beast::string_view target)
|
||||||
{
|
{
|
||||||
// Request path must be absolute and not contain "..".
|
// Request path must be absolute and not contain "..".
|
||||||
if (target.empty() || target[0] != '/' || target.find("..") != std::string::npos)
|
if (target.empty() || target[0] != '/' || target.find("..") != std::string::npos)
|
||||||
{
|
{
|
||||||
response_->result(http::status::not_found);
|
send_bad_response(
|
||||||
response_->set(http::field::content_type, "text/plain");
|
http::status::not_found,
|
||||||
response_->body = "File not found\r\n";
|
"File not found\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string full_path = doc_root_;
|
std::string full_path = doc_root_;
|
||||||
full_path.append(target.data(), target.size());
|
full_path.append(
|
||||||
|
target.data(),
|
||||||
|
target.size());
|
||||||
|
|
||||||
// Open the file to send back.
|
http::file_body::value_type file;
|
||||||
std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary);
|
beast::error_code ec;
|
||||||
if (!is)
|
file.open(
|
||||||
|
full_path.c_str(),
|
||||||
|
beast::file_mode::read,
|
||||||
|
ec);
|
||||||
|
if(ec)
|
||||||
{
|
{
|
||||||
response_->result(http::status::not_found);
|
send_bad_response(
|
||||||
response_->set(http::field::content_type, "text/plain");
|
http::status::not_found,
|
||||||
response_->body = "File not found\r\n";
|
"File not found\r\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill out the reply to be sent to the client.
|
file_response_.emplace(
|
||||||
response_->set(http::field::content_type, mime_type(target.to_string()));
|
std::piecewise_construct,
|
||||||
response_->body.clear();
|
std::make_tuple(),
|
||||||
for (char buf[2048]; is.read(buf, sizeof(buf)).gcount() > 0;)
|
std::make_tuple(alloc_));
|
||||||
response_->body.append(buf, static_cast<std::size_t>(is.gcount()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void write_response()
|
file_response_->result(http::status::ok);
|
||||||
{
|
file_response_->set(http::field::server, "Beast");
|
||||||
response_->prepare_payload();
|
file_response_->set(http::field::connection, "close");
|
||||||
serializer_.emplace(*response_);
|
file_response_->set(http::field::content_type, mime_type(target.to_string()));
|
||||||
|
file_response_->body = std::move(file);
|
||||||
|
file_response_->prepare_payload();
|
||||||
|
|
||||||
|
file_serializer_.emplace(*file_response_);
|
||||||
|
|
||||||
http::async_write(
|
http::async_write(
|
||||||
socket_,
|
socket_,
|
||||||
*serializer_,
|
*file_serializer_,
|
||||||
[this](beast::error_code ec)
|
[this](beast::error_code ec)
|
||||||
{
|
{
|
||||||
socket_.shutdown(tcp::socket::shutdown_send, ec);
|
socket_.shutdown(tcp::socket::shutdown_send, ec);
|
||||||
serializer_.reset();
|
file_serializer_.reset();
|
||||||
response_.reset();
|
file_response_.reset();
|
||||||
accept();
|
accept();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user