Refactor beast core, http, tests, and examples:

* Fix warnings
* Port cmake scripts to linux
* Add command line options for running test suites
* Add examples to CMakeLists
* Return std::uint64_t from writer::content_length
* basic_parser::write takes asio::const_buffer instead of pointer and size
* Turn message test back on now that it passes
* Rename to http::headers, use std::allocator, remove http_headers
* http::message::method is now a string
* Refactor to_string for ConstBufferSequence
* Remove chunk_encode from the public interface
* Initialize members for default constructed iterators
* Disallow default construction for dependent buffer sequences

Refactor http::message serialization:

* Serialization no longer creates a copy of the
  headers and modifies them
* New function prepare(), sets Connection, Transfer-Encoding,
  Content-Length based on the body attributes and caller options.
  Callers can use prepare() to have the fields set automatically,
  or they can set the fields manually.
* Use write for operator<<
* Tests for serialization
This commit is contained in:
Vinnie Falco
2016-04-29 06:04:40 -04:00
parent f3c3e0bfff
commit 47dc31d8c2
69 changed files with 1315 additions and 953 deletions

View File

@@ -8,8 +8,8 @@
#ifndef BEAST_HTTP_IMPL_WRITE_IPP
#define BEAST_HTTP_IMPL_WRITE_IPP
#include <beast/http/chunk_encode.hpp>
#include <beast/http/resume_context.hpp>
#include <beast/http/detail/chunk_encode.hpp>
#include <beast/http/detail/write_preparation.hpp>
#include <beast/buffer_cat.hpp>
#include <beast/bind_handler.hpp>
@@ -20,6 +20,8 @@
#include <boost/logic/tribool.hpp>
#include <condition_variable>
#include <mutex>
#include <ostream>
#include <sstream>
#include <type_traits>
namespace beast {
@@ -77,7 +79,7 @@ class write_op
if(d.wp.chunked)
boost::asio::async_write(d.s,
buffer_cat(d.wp.sb.data(),
chunk_encode(buffers)),
detail::chunk_encode(buffers)),
std::move(self_));
else
boost::asio::async_write(d.s,
@@ -104,7 +106,7 @@ class write_op
// write body
if(d.wp.chunked)
boost::asio::async_write(d.s,
chunk_encode(buffers),
detail::chunk_encode(buffers),
std::move(self_));
else
boost::asio::async_write(d.s,
@@ -269,7 +271,7 @@ operator()(error_code ec, std::size_t, bool again)
// write final chunk
d.state = 5;
boost::asio::async_write(d.s,
chunk_encode_final(), std::move(*this));
detail::chunk_encode_final(), std::move(*this));
return;
case 5:
@@ -311,7 +313,7 @@ public:
// write headers and body
if(chunked_)
boost::asio::write(stream_, buffer_cat(
sb_.data(), chunk_encode(buffers)), ec_);
sb_.data(), detail::chunk_encode(buffers)), ec_);
else
boost::asio::write(stream_, buffer_cat(
sb_.data(), buffers), ec_);
@@ -340,7 +342,7 @@ public:
// write body
if(chunked_)
boost::asio::write(stream_,
chunk_encode(buffers), ec_);
detail::chunk_encode(buffers), ec_);
else
boost::asio::write(stream_, buffers, ec_);
}
@@ -357,6 +359,8 @@ write(SyncWriteStream& stream,
message<isRequest, Body, Headers> const& msg,
boost::system::error_code& ec)
{
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
"SyncWriteStream requirements not met");
detail::write_preparation<isRequest, Body, Headers> wp(msg);
wp.init(ec);
if(ec)
@@ -420,7 +424,7 @@ write(SyncWriteStream& stream,
// final body chunk with the final chunk delimiter.
//
// write final chunk
boost::asio::write(stream, chunk_encode_final(), ec);
boost::asio::write(stream, detail::chunk_encode_final(), ec);
if(ec)
return;
}
@@ -450,6 +454,68 @@ async_write(AsyncWriteStream& stream,
return completion.result.get();
}
namespace detail {
class ostream_SyncStream
{
std::ostream& os_;
public:
ostream_SyncStream(std::ostream& os)
: os_(os)
{
}
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers)
{
error_code ec;
auto const n = write_some(buffers, ec);
if(ec)
throw boost::system::system_error{ec};
return n;
}
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers,
error_code& ec)
{
std::size_t n = 0;
using boost::asio::buffer_cast;
using boost::asio::buffer_size;
for(auto const& buffer : buffers)
{
os_.write(buffer_cast<char const*>(buffer),
buffer_size(buffer));
if(os_.fail())
{
ec = boost::system::errc::make_error_code(
boost::system::errc::no_stream_resources);
break;
}
n += buffer_size(buffer);
}
return n;
}
};
} // detail
template<bool isRequest, class Body, class Headers>
std::ostream&
operator<<(std::ostream& os,
message<isRequest, Body, Headers> const& msg)
{
detail::ostream_SyncStream oss(os);
error_code ec;
write(oss, msg, ec);
if(ec && ec != boost::asio::error::eof)
throw boost::system::system_error{ec};
return os;
}
} // http
} // beast