Better WebSocket decorator:

* Caller provided type can omit one or both overloads
* Omitted overloads yield default behavior
* Documentation no longer refers to a detail type
This commit is contained in:
Vinnie Falco
2016-09-25 12:12:23 -04:00
parent 42073a925a
commit 41a8342d3b
3 changed files with 78 additions and 23 deletions

View File

@@ -3,6 +3,7 @@
* Add missing rebind to handler_alloc
* Fix error handling in http server examples
* Fix CMake scripts for MinGW
* Better WebSocket decorator
--------------------------------------------------------------------------------

View File

@@ -11,6 +11,7 @@
#include <beast/http/empty_body.hpp>
#include <beast/http/message.hpp>
#include <beast/http/string_body.hpp>
#include <beast/version.hpp>
#include <utility>
namespace beast {
@@ -40,6 +41,32 @@ class decorator : public abstract_decorator
{
T t_;
class call_req_possible
{
template<class U, class R = decltype(
std::declval<U>().operator()(
std::declval<request_type&>()),
std::true_type{})>
static R check(int);
template<class>
static std::false_type check(...);
public:
using type = decltype(check<T>(0));
};
class call_res_possible
{
template<class U, class R = decltype(
std::declval<U>().operator()(
std::declval<response_type&>()),
std::true_type{})>
static R check(int);
template<class>
static std::false_type check(...);
public:
using type = decltype(check<T>(0));
};
public:
decorator() = default;
@@ -56,38 +83,45 @@ public:
void
operator()(request_type& req) override
{
t_(req);
(*this)(req, typename call_req_possible::type{});
}
void
operator()(response_type& resp) override
{
t_(resp);
(*this)(resp, typename call_res_possible::type{});
}
private:
void
operator()(request_type& req, std::true_type)
{
t_(req);
}
void
operator()(request_type& req, std::false_type)
{
req.headers.replace("User-Agent",
std::string{"Beast/"} + BEAST_VERSION_STRING);
}
void
operator()(response_type& res, std::true_type)
{
t_(res);
}
void
operator()(response_type& res, std::false_type)
{
res.headers.replace("Server",
std::string{"Beast/"} + BEAST_VERSION_STRING);
}
};
struct default_decorator
{
static
char const*
version()
{
return "Beast.WSProto/1.0";
}
template<class Body, class Headers>
void
operator()(http::message<true, Body, Headers>& req)
{
req.headers.replace("User-Agent", version());
}
template<class Body, class Headers>
void
operator()(http::message<false, Body, Headers>& resp)
{
resp.headers.replace("Server", version());
}
};
using decorator_type =

View File

@@ -177,9 +177,29 @@ public:
wr_frag_size_ = o.value;
}
/// Set the decorator used for HTTP messages
/** Set the decorator used for HTTP messages.
The value for this option is a callable type with two
optional signatures:
@code
void(request_type&);
void(response_type&);
@endcode
If a matching signature is provided, the callable type
will be invoked with the HTTP request or HTTP response
object as appropriate. When a signature is omitted,
a default consisting of the string Beast followed by
the version number is used.
*/
void
#if GENERATING_DOCS
set_option(implementation_defined o)
#else
set_option(detail::decorator_type o)
#endif
{
d_ = std::move(o);
}