2016-05-07 17:06:46 -04:00
|
|
|
//
|
2017-02-06 20:07:03 -05:00
|
|
|
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
2016-05-07 17:06:46 -04:00
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
2017-07-20 08:01:46 -07:00
|
|
|
|
|
|
|
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
|
|
|
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
|
|
|
|
|
2016-11-10 05:34:49 -05:00
|
|
|
#include <beast/core/error.hpp>
|
|
|
|
#include <beast/http/message.hpp>
|
2017-07-20 08:01:46 -07:00
|
|
|
#include <boost/asio/buffer.hpp>
|
2017-04-10 19:29:35 -07:00
|
|
|
#include <boost/assert.hpp>
|
2017-07-20 08:01:46 -07:00
|
|
|
#include <boost/filesystem.hpp>
|
2017-05-08 12:41:45 -07:00
|
|
|
#include <boost/optional.hpp>
|
2017-06-08 05:43:57 -07:00
|
|
|
#include <algorithm>
|
2017-07-20 08:01:46 -07:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
namespace beast {
|
|
|
|
namespace http {
|
|
|
|
|
|
|
|
struct file_body
|
|
|
|
{
|
|
|
|
using value_type = std::string;
|
|
|
|
|
2017-06-05 21:11:33 -07:00
|
|
|
/// Returns the content length of the body in a message.
|
|
|
|
template<bool isRequest, class Fields>
|
|
|
|
static
|
|
|
|
std::uint64_t
|
|
|
|
size(
|
|
|
|
message<isRequest, file_body, Fields> const& m)
|
|
|
|
{
|
|
|
|
return boost::filesystem::file_size(m.body.c_str());
|
|
|
|
}
|
|
|
|
|
2017-05-28 09:05:29 -07:00
|
|
|
class reader
|
2017-07-20 08:01:46 -07:00
|
|
|
{
|
2016-08-02 13:37:41 +02:00
|
|
|
std::uint64_t size_ = 0;
|
2016-04-29 06:04:40 -04:00
|
|
|
std::uint64_t offset_ = 0;
|
2017-07-20 08:01:46 -07:00
|
|
|
std::string const& path_;
|
|
|
|
FILE* file_ = nullptr;
|
|
|
|
char buf_[4096];
|
|
|
|
|
|
|
|
public:
|
2017-05-08 12:41:45 -07:00
|
|
|
using is_deferred = std::true_type;
|
|
|
|
|
|
|
|
using const_buffers_type =
|
|
|
|
boost::asio::const_buffers_1;
|
|
|
|
|
2017-05-28 09:05:29 -07:00
|
|
|
reader(reader&&) = default;
|
|
|
|
reader(reader const&) = delete;
|
|
|
|
reader& operator=(reader const&) = delete;
|
2017-07-20 08:01:46 -07:00
|
|
|
|
2016-11-10 05:34:49 -05:00
|
|
|
template<bool isRequest, class Fields>
|
2017-05-28 09:05:29 -07:00
|
|
|
reader(message<isRequest,
|
2017-05-08 12:41:45 -07:00
|
|
|
file_body, Fields> const& m)
|
2017-07-20 08:01:46 -07:00
|
|
|
: path_(m.body)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2017-05-28 09:05:29 -07:00
|
|
|
~reader()
|
2017-07-20 08:01:46 -07:00
|
|
|
{
|
|
|
|
if(file_)
|
|
|
|
fclose(file_);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-05-08 12:41:45 -07:00
|
|
|
init(error_code& ec)
|
2017-07-20 08:01:46 -07:00
|
|
|
{
|
|
|
|
file_ = fopen(path_.c_str(), "rb");
|
|
|
|
if(! file_)
|
2017-06-08 05:43:57 -07:00
|
|
|
ec = error_code{errno, system_category()};
|
2017-07-20 08:01:46 -07:00
|
|
|
else
|
|
|
|
size_ = boost::filesystem::file_size(path_);
|
|
|
|
}
|
|
|
|
|
2017-05-08 12:41:45 -07:00
|
|
|
boost::optional<std::pair<const_buffers_type, bool>>
|
|
|
|
get(error_code& ec)
|
2017-07-20 08:01:46 -07:00
|
|
|
{
|
2017-06-08 05:43:57 -07:00
|
|
|
auto const amount = std::min<std::uint64_t>(size_ - offset_, sizeof(buf_));
|
|
|
|
auto const nread = fread(buf_, 1, amount, file_);
|
2017-03-31 11:15:27 -04:00
|
|
|
if(ferror(file_))
|
|
|
|
{
|
2017-05-08 12:41:45 -07:00
|
|
|
ec = error_code(errno, system_category());
|
|
|
|
return boost::none;
|
2017-03-31 11:15:27 -04:00
|
|
|
}
|
2017-04-10 19:29:35 -07:00
|
|
|
BOOST_ASSERT(nread != 0);
|
|
|
|
offset_ += nread;
|
2017-06-08 05:43:57 -07:00
|
|
|
return {{const_buffers_type{buf_, nread}, offset_ >= size_}};
|
2017-07-20 08:01:46 -07:00
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
} // http
|
|
|
|
} // beast
|
|
|
|
|
|
|
|
#endif
|