From a6cb4fdfb28c3c84ed9c5ca9f94d5d4c6fdebbbb Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Mon, 20 Jun 2016 11:17:26 -0400 Subject: [PATCH] Remove deprecated example http::stream wrapper --- CHANGELOG | 5 + examples/http_stream.hpp | 480 --------------------------------------- examples/http_stream.ipp | 412 --------------------------------- 3 files changed, 5 insertions(+), 892 deletions(-) delete mode 100644 examples/http_stream.hpp delete mode 100644 examples/http_stream.ipp diff --git a/CHANGELOG b/CHANGELOG index df5b852c..cf82084b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,11 @@ 1.0.0-b7 +* Fix prepare by calling init. prepare() can throw depending on the + implementation of Writer. Publicly provided beast::http writers never throw. +* Fixes to example HTTP server * Fully qualify ambiguous calls to read and parse +* Remove deprecated http::stream wrapper +* Example HTTP server now calculates the MIME-type -------------------------------------------------------------------------------- diff --git a/examples/http_stream.hpp b/examples/http_stream.hpp deleted file mode 100644 index eb07f637..00000000 --- a/examples/http_stream.hpp +++ /dev/null @@ -1,480 +0,0 @@ -// -// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// 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) -// - -#ifndef BEAST_HTTP_STREAM_H_INCLUDED -#define BEAST_HTTP_STREAM_H_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace beast { -namespace http { - -namespace detail { - -class stream_base -{ -protected: - struct op - : boost::intrusive::list_base_hook< - boost::intrusive::link_mode< - boost::intrusive::normal_link>> - { - virtual ~op() = default; - virtual void operator()() = 0; - virtual void cancel() = 0; - }; - - using op_list = typename boost::intrusive::make_list< - op, boost::intrusive::constant_time_size>::type; - - op_list wr_q_; - bool wr_active_ = false; -}; - -} // detail - -/** Provides message-oriented functionality using HTTP. - - The stream class template provides asynchronous and blocking - message-oriented functionality necessary for clients and servers - to utilize the HTTP protocol. - - @par Thread Safety - @e Distinct @e objects: Safe.@n - @e Shared @e objects: Unsafe. The application must ensure that - all asynchronous operations are performed within the same - implicit or explicit strand. - - @par Example - - To use the class template with an `ip::tcp::socket`, you would write: - - @code - http::stream hs(io_service); - @endcode - Alternatively, you can write: - @code - ip::tcp::socket sock(io_service); - http::stream hs(sock); - @endcode - - @note A stream object must not be destroyed while there are - pending asynchronous operations associated with it. - - @par Concepts - AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream. - */ -template> -class stream : public detail::stream_base -{ - NextLayer next_layer_; - basic_streambuf rd_buf_; - -public: - /// The type of the next layer. - using next_layer_type = - typename std::remove_reference::type; - - /// The type of the lowest layer. - using lowest_layer_type = - typename next_layer_type::lowest_layer_type; - - /// The type of endpoint of the lowest layer. - using endpoint_type = - typename lowest_layer_type::endpoint_type; - - /// The protocol of the next layer. - using protocol_type = - typename lowest_layer_type::protocol_type; - - /// The type of resolver of the next layer. - using resolver_type = - typename protocol_type::resolver; - - /** Destructor. - - @note A stream object must not be destroyed while there - are pending asynchronous operations associated with it. - */ - ~stream(); - - /** Move constructor. - - Undefined behavior if operations are active or pending. - */ - stream(stream&&) = default; - - /** Move assignment. - - Undefined behavior if operations are active or pending. - */ - stream& operator=(stream&&) = default; - - /** Construct a HTTP stream. - - This constructor creates a HTTP stream and initialises - the next layer. - - @throws Any exceptions thrown by the Stream constructor. - - @param args The arguments to be passed to initialise the - next layer. The arguments are forwarded to the next layer's - constructor. - */ - template - explicit - stream(Args&&... args); - - /** Get the io_service associated with the stream. - - This function may be used to obtain the io_service object - that the stream uses to dispatch handlers for asynchronous - operations. - - @return A reference to the io_service object that the stream - will use to dispatch handlers. Ownership is not transferred - to the caller. - */ - boost::asio::io_service& - get_io_service() - { - return next_layer_.lowest_layer().get_io_service(); - } - - /** Get a reference to the next layer. - - This function returns a reference to the next layer - in a stack of stream layers. - - @return A reference to the next layer in the stack of - stream layers. Ownership is not transferred to the caller. - */ - next_layer_type& - next_layer() - { - return next_layer_; - } - - /** Get a reference to the next layer. - - This function returns a reference to the next layer in a - stack of stream layers. - - @return A reference to the next layer in the stack of - stream layers. Ownership is not transferred to the caller. - */ - next_layer_type const& - next_layer() const - { - return next_layer_; - } - - /** Get a reference to the lowest layer. - - This function returns a reference to the lowest layer - in a stack of stream layers. - - @return A reference to the lowest layer in the stack of - stream layers. Ownership is not transferred to the caller. - */ - lowest_layer_type& - lowest_layer() - { - return next_layer_.lowest_layer(); - } - - /** Get a reference to the lowest layer. - - This function returns a reference to the lowest layer - in a stack of stream layers. - - @return A reference to the lowest layer in the stack of - stream layers. Ownership is not transferred to the caller. - */ - lowest_layer_type const& - lowest_layer() const - { - return next_layer_.lowest_layer(); - } - - /** Cancel pending operations. - - This will cancel all of the asynchronous operations pending, - including pipelined writes that have not been started. Handlers for - canceled writes will be called with - `boost::asio::error::operation_aborted`. - - @throws boost::system::system_error Thrown on failure. - */ - void - cancel() - { - error_code ec; - cancel(ec); - if(ec) - throw system_error{ec}; - } - - /** Cancel pending operations. - - This will cancel all of the asynchronous operations pending, - including pipelined writes that have not been started. Handlers for - canceled writes will be called with - `boost::asio::error::operation_aborted`. - - @param ec Set to indicate what error occurred, if any. - */ - void - cancel(error_code& ec); - - /** Read a HTTP message from the stream. - - This function is used to read a single HTTP message from the stream. - The call will block until one of the followign conditions is true: - - @li A message has been read. - - @li An error occurred. - - The operation is implemented in terms of zero or more calls to the - next layer's `read_some` function. - - @param msg An object used to store the message. The previous - contents of the object will be overwritten. - - @throws boost::system::system_error Thrown on failure. - */ - template - void - read(message_v1& msg) - { - error_code ec; - read(msg, ec); - if(ec) - throw system_error{ec}; - } - - /** Read a HTTP message from the stream. - - This function is used to read a single HTTP message from the stream. - The call will block until one of the followign conditions is true: - - @li A message has been read. - - @li An error occurred. - - The operation is implemented in terms of zero or more calls to the - next layer's `read_some` function. - - @param msg An object used to store the message. The previous - contents of the object will be overwritten. - - @param ec Set to indicate what error occurred, if any. - */ - template - void - read(message_v1& msg, - error_code& ec); - - /** Start reading a HTTP message from the stream asynchronously. - - This function is used to asynchronously read a single HTTP message - from the stream. The function call always returns immediately. The - asynchronous operation will continue until one of the following - conditions is true: - - @li The message has been written. - - @li An error occurred. - - This operation is implemented in terms of zero or more calls to the - next layer's async_read_some function, and is known as a composed - operation. The program must ensure that the stream performs no other - read operations or any other composed operations that perform reads - until this operation completes. - - @param msg An object used to store the message. The previous - contents of the object will be overwritten. Ownership of the message - is not transferred; the caller must guarantee that the object remains - valid until the handler is called. - - @param handler The handler to be called when the request completes. - Copies will be made of the handler as required. The equivalent - function signature of the handler must be: - @code void handler( - error_code const& error // result of operation - ); @endcode - Regardless of whether the asynchronous operation completes - immediately or not, the handler will not be invoked from within - this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). - */ - template -#if GENERATING_DOCS - void_or_deduced -#else - typename async_completion< - ReadHandler, void(error_code)>::result_type -#endif - async_read(message_v1& msg, - ReadHandler&& handler); - - /** Write a HTTP message to the stream. - - This function is used to write a single HTTP message to the - stream. The call will block until one of the following conditions - is true: - - @li The entire message is sent. - - @li An error occurred. - - If the semantics of the message require that the connection is - closed to indicate the end of the content body, - `boost::asio::error::eof` is thrown after the message is sent. - successfuly. The caller is responsible for actually closing the - connection. For regular TCP/IP streams this means shutting down the - send side, while SSL streams may call the SSL shutdown function. - - @param msg The message to send. - - @throws boost::system::system_error Thrown on failure. - */ - template - void - write(message_v1 const& msg) - { - error_code ec; - write(msg, ec); - if(ec) - throw system_error{ec}; - } - - /** Write a HTTP message to the stream. - - This function is used to write a single HTTP message to the - stream. The call will block until one of the following conditions - is true: - - @li The entire message is sent. - - @li An error occurred. - - If the semantics of the message require that the connection is - closed to indicate the end of the content body, - `boost::asio::error::eof` is returned after the message is sent. - successfuly. The caller is responsible for actually closing the - connection. For regular TCP/IP streams this means shutting down the - send side, while SSL streams may call the SSL shutdown function. - - @param msg The message to send. - - @param ec Set to the error, if any occurred. - */ - template - void - write(message_v1 const& msg, - error_code& ec); - - /** Start pipelining a HTTP message to the stream asynchronously. - - This function is used to queue a message to be sent on the stream. - Unlike the free function, this version will place the message on an - outgoing message queue if there is already a write pending. - - If the semantics of the message require that the connection is - closed to indicate the end of the content body, the handler - is called with the error `boost::asio::error::eof` after the message - has been sent successfully. The caller is responsible for actually - closing the connection. For regular TCP/IP streams this means - shutting down the send side, while SSL streams may call the SSL - `async_shutdown` function. - - @param msg The message to send. A copy of the message will be made. - - @param handler The handler to be called when the request completes. - Copies will be made of the handler as required. The equivalent - function signature of the handler must be: - @code void handler( - error_code const& error // result of operation - ); @endcode - Regardless of whether the asynchronous operation completes - immediately or not, the handler will not be invoked from within - this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). - */ - template -#if GENERATING_DOCS - void_or_deduced -#else - typename async_completion< - WriteHandler, void(error_code)>::result_type -#endif - async_write(message_v1 const& msg, - WriteHandler&& handler); - - /** Start pipelining a HTTP message to the stream asynchronously. - - This function is used to queue a message to be sent on the stream. - Unlike the free function, this version will place the message on an - outgoing message queue if there is already a write pending. - - If the semantics of the message require that the connection is - closed to indicate the end of the content body, the handler - is called with the error boost::asio::error::eof. The caller is - responsible for actually closing the connection. For regular - TCP/IP streams this means shutting down the send side, while SSL - streams may call the SSL async_shutdown function. - - @param msg The message to send. Ownership of the message, which - must be movable, is transferred to the implementation. The message - will not be destroyed until the asynchronous operation completes. - - @param handler The handler to be called when the request completes. - Copies will be made of the handler as required. The equivalent - function signature of the handler must be: - @code void handler( - error_code const& error // result of operation - ); @endcode - Regardless of whether the asynchronous operation completes - immediately or not, the handler will not be invoked from within - this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). - */ - template - #if GENERATING_DOCS - void_or_deduced - #else - typename async_completion< - WriteHandler, void(error_code)>::result_type - #endif - async_write(message_v1&& msg, - WriteHandler&& handler); - -private: - template class read_op; - template class write_op; - - void - cancel_all(); -}; - -} // http -} // beast - -#include "http_stream.ipp" - -#endif diff --git a/examples/http_stream.ipp b/examples/http_stream.ipp deleted file mode 100644 index 4e9df6e7..00000000 --- a/examples/http_stream.ipp +++ /dev/null @@ -1,412 +0,0 @@ -// -// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com) -// -// 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) -// - -#ifndef BEAST_HTTP_STREAM_IPP_INCLUDED -#define BEAST_HTTP_STREAM_IPP_INCLUDED - -#include -#include -#include -#include -#include -#include - -namespace beast { -namespace http { - -template -template -class stream::read_op -{ - using alloc_type = - handler_alloc; - - struct data - { - stream& s; - message_v1& m; - Handler h; - bool cont; - int state = 0; - - template - data(DeducedHandler&& h_, stream& s_, - message_v1& m_) - : s(s_) - , m(m_) - , h(std::forward(h_)) - , cont(boost_asio_handler_cont_helpers:: - is_continuation(h)) - { - } - }; - - std::shared_ptr d_; - -public: - read_op(read_op&&) = default; - read_op(read_op const&) = default; - - template - read_op(DeducedHandler&& h, - stream& s, Args&&... args) - : d_(std::allocate_shared(alloc_type{h}, - std::forward(h), s, - std::forward(args)...)) - { - (*this)(error_code{}, false); - } - - void operator()(error_code const& ec, bool again = true); - - friend - void* asio_handler_allocate( - std::size_t size, read_op* op) - { - return boost_asio_handler_alloc_helpers:: - allocate(size, op->d_->h); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, read_op* op) - { - return boost_asio_handler_alloc_helpers:: - deallocate(p, size, op->d_->h); - } - - friend - bool asio_handler_is_continuation(read_op* op) - { - return op->d_->cont; - } - - template - friend - void asio_handler_invoke(Function&& f, read_op* op) - { - return boost_asio_handler_invoke_helpers:: - invoke(f, op->d_->h); - } -}; - -template -template -void -stream:: -read_op:: -operator()(error_code const& ec, bool again) -{ - auto& d = *d_; - d.cont = d.cont || again; - while(! ec && d.state != 99) - { - switch(d.state) - { - case 0: - d.state = 99; - beast::http::async_read(d.s.next_layer_, - d.s.rd_buf_, d.m, std::move(*this)); - return; - } - } - d.h(ec); -} - -//------------------------------------------------------------------------------ - -template -template -class stream::write_op : public op -{ - using alloc_type = - handler_alloc; - - struct data - { - stream& s; - message_v1 m; - Handler h; - bool cont; - int state = 0; - - template - data(DeducedHandler&& h_, stream& s_, - message_v1 const& m_, - bool cont_) - : s(s_) - , m(m_) - , h(std::forward(h_)) - , cont(cont_) - { - } - - template - data(DeducedHandler&& h_, stream& s_, - message_v1&& m_, - bool cont_) - : s(s_) - , m(std::move(m_)) - , h(std::forward(h_)) - , cont(cont_) - { - } - }; - - std::shared_ptr d_; - -public: - write_op(write_op&&) = default; - write_op(write_op const&) = default; - - template - write_op(DeducedHandler&& h, - stream& s, Args&&... args) - : d_(std::allocate_shared(alloc_type{h}, - std::forward(h), s, - std::forward(args)...)) - { - } - - void - operator()() override - { - (*this)(error_code{}, false); - } - - void cancel() override; - - void operator()(error_code const& ec, bool again = true); - - friend - void* asio_handler_allocate( - std::size_t size, write_op* op) - { - return boost_asio_handler_alloc_helpers:: - allocate(size, op->d_->h); - } - - friend - void asio_handler_deallocate( - void* p, std::size_t size, write_op* op) - { - return boost_asio_handler_alloc_helpers:: - deallocate(p, size, op->d_->h); - } - - friend - bool asio_handler_is_continuation(write_op* op) - { - return op->d_->cont; - } - - template - friend - void asio_handler_invoke(Function&& f, write_op* op) - { - return boost_asio_handler_invoke_helpers:: - invoke(f, op->d_->h); - } -}; - -template -template -void -stream:: -write_op:: -cancel() -{ - auto& d = *d_; - d.s.get_io_service().post( - bind_handler(std::move(*this), - boost::asio::error::operation_aborted)); -} - -template -template -void -stream:: -write_op:: -operator()(error_code const& ec, bool again) -{ - auto& d = *d_; - d.cont = d.cont || again; - while(! ec && d.state != 99) - { - switch(d.state) - { - case 0: - d.state = 99; - beast::http::async_write(d.s.next_layer_, - d.m, std::move(*this)); - return; - } - } - d.h(ec); - if(! d.s.wr_q_.empty()) - { - auto& op = d.s.wr_q_.front(); - op(); - // VFALCO Use allocator - delete &op; - d.s.wr_q_.pop_front(); - } - else - { - d.s.wr_active_ = false; - } -} - -//------------------------------------------------------------------------------ - -template -stream:: -~stream() -{ - // Can't destroy with pending operations! - assert(wr_q_.empty()); -} - -template -template -stream:: -stream(Args&&... args) - : next_layer_(std::forward(args)...) -{ -} - -template -void -stream:: -cancel(error_code& ec) -{ - cancel_all(); - lowest_layer().cancel(ec); -} - -template -template -void -stream:: -read(message_v1& msg, - error_code& ec) -{ - beast::http::read(next_layer_, rd_buf_, msg, ec); -} - -template -template -auto -stream:: -async_read(message_v1& msg, - ReadHandler&& handler) -> - typename async_completion< - ReadHandler, void(error_code)>::result_type -{ - async_completion< - ReadHandler, void(error_code) - > completion(handler); - read_op{ - completion.handler, *this, msg}; - return completion.result.get(); -} - -template -template -void -stream:: -write(message_v1 const& msg, - error_code& ec) -{ - beast::http::write(next_layer_, msg, ec); -} - -template -template -auto -stream:: -async_write(message_v1 const& msg, - WriteHandler&& handler) -> - typename async_completion< - WriteHandler, void(error_code)>::result_type -{ - async_completion< - WriteHandler, void(error_code)> completion(handler); - auto const cont = wr_active_ || - boost_asio_handler_cont_helpers::is_continuation(handler); - if(! wr_active_) - { - wr_active_ = true; - write_op{ - completion.handler, *this, msg, cont }(); - } - else - { - // VFALCO Use allocator - wr_q_.push_back(*new write_op( - completion.handler, *this, msg, cont)); - } - return completion.result.get(); -} - -template -template -auto -stream:: -async_write(message_v1&& msg, - WriteHandler&& handler) -> - typename async_completion< - WriteHandler, void(error_code)>::result_type -{ - async_completion< - WriteHandler, void(error_code)> completion(handler); - auto const cont = wr_active_ || - boost_asio_handler_cont_helpers::is_continuation(handler); - if(! wr_active_) - { - wr_active_ = true; - write_op{completion.handler, - *this, std::move(msg), cont}(); - } - else - { - // VFALCO Use allocator - wr_q_.push_back(*new write_op(completion.handler, - *this, std::move(msg), cont)); - } - return completion.result.get(); -} - -template -void -stream:: -cancel_all() -{ - for(auto it = wr_q_.begin(); it != wr_q_.end();) - { - auto& op = *it++; - op.cancel(); - // VFALCO Use allocator - delete &op; - } - wr_q_.clear(); -} - -} // http -} // beast - -#endif