forked from boostorg/beast
Refactor http::header contents (API Change):
fix #124 The http::header data members "method", "url", and "reason" are changed from data members, to pairs of get and set functions which forward the call to the Fields type used to instantiate the template. Previously, these data members were implemented using std::string. With this change, the implementation of the Fields type used to instantiate the template is now in control of the representation of those values. This permits custom memory allocation strategies including uniform use of the Allocator type already provided to beast::http::basic_fields.
This commit is contained in:
1 parent
dd02097d26
commit
ff5e659545
30 files changed
+319
-213
No files matched your search
@@ -94,7 +94,7 @@ enum class parse_state
|
||||
void
|
||||
on_request(
|
||||
boost::string_ref const& method,
|
||||
boost::string_ref const& path,
|
||||
boost::string_ref const& target,
|
||||
int version,
|
||||
error_code& ec);
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ protected:
|
||||
|
||||
static
|
||||
boost::string_ref
|
||||
parse_path(char const*& it)
|
||||
parse_target(char const*& it)
|
||||
{
|
||||
auto const first = it;
|
||||
while(is_pathchar(*it))
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <beast/core/detail/empty_base_optimization.hpp>
|
||||
#include <beast/http/detail/fields.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <memory>
|
||||
@@ -297,6 +298,46 @@ public:
|
||||
replace(name,
|
||||
boost::lexical_cast<std::string>(value));
|
||||
}
|
||||
|
||||
#if BEAST_DOXYGEN
|
||||
private:
|
||||
#endif
|
||||
|
||||
boost::string_ref
|
||||
method() const
|
||||
{
|
||||
return (*this)[":method"];
|
||||
}
|
||||
|
||||
void
|
||||
method(boost::string_ref const& s)
|
||||
{
|
||||
return this->replace(":method", s);
|
||||
}
|
||||
|
||||
boost::string_ref
|
||||
target() const
|
||||
{
|
||||
return (*this)[":target"];
|
||||
}
|
||||
|
||||
void
|
||||
target(boost::string_ref const& s)
|
||||
{
|
||||
return this->replace(":target", s);
|
||||
}
|
||||
|
||||
boost::string_ref
|
||||
reason() const
|
||||
{
|
||||
return (*this)[":reason"];
|
||||
}
|
||||
|
||||
void
|
||||
reason(boost::string_ref const& s)
|
||||
{
|
||||
return this->replace(":reason", s);
|
||||
}
|
||||
};
|
||||
|
||||
/// A typical HTTP header fields container
|
||||
|
||||
@@ -112,10 +112,8 @@ private:
|
||||
boost::string_ref const& path,
|
||||
int version, error_code&)
|
||||
{
|
||||
h_.url = std::string{
|
||||
path.data(), path.size()};
|
||||
h_.method = std::string{
|
||||
method.data(), method.size()};
|
||||
h_.target(path);
|
||||
h_.method(method);
|
||||
h_.version = version;
|
||||
}
|
||||
|
||||
@@ -125,9 +123,8 @@ private:
|
||||
int version, error_code&)
|
||||
{
|
||||
h_.status = status;
|
||||
h_.reason = std::string{
|
||||
reason.data(), reason.size()};
|
||||
h_.version = version;
|
||||
h_.reason(reason);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -396,8 +396,8 @@ parse_startline(char const*& it,
|
||||
return;
|
||||
}
|
||||
|
||||
auto const path = parse_path(it);
|
||||
if(path.empty())
|
||||
auto const target = parse_target(it);
|
||||
if(target.empty())
|
||||
{
|
||||
ec = error::bad_path;
|
||||
return;
|
||||
@@ -416,7 +416,7 @@ parse_startline(char const*& it,
|
||||
}
|
||||
|
||||
impl().on_request(
|
||||
method, path, version, ec);
|
||||
method, target, version, ec);
|
||||
if(ec)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@ swap(
|
||||
{
|
||||
using std::swap;
|
||||
swap(m1.version, m2.version);
|
||||
swap(m1.method, m2.method);
|
||||
swap(m1.url, m2.url);
|
||||
swap(m1.fields, m2.fields);
|
||||
}
|
||||
|
||||
@@ -42,7 +40,6 @@ swap(
|
||||
using std::swap;
|
||||
swap(a.version, b.version);
|
||||
swap(a.status, b.status);
|
||||
swap(a.reason, b.reason);
|
||||
swap(a.fields, b.fields);
|
||||
}
|
||||
|
||||
@@ -199,7 +196,7 @@ prepare(message<isRequest, Body, Fields>& msg,
|
||||
{
|
||||
using beast::detail::ci_equal;
|
||||
if(*pi.content_length > 0 ||
|
||||
ci_equal(msg.method, "POST"))
|
||||
ci_equal(msg.method(), "POST"))
|
||||
{
|
||||
msg.fields.insert(
|
||||
"Content-Length", *pi.content_length);
|
||||
|
||||
@@ -37,9 +37,9 @@ write_start_line(DynamicBuffer& dynabuf,
|
||||
header<true, Fields> const& msg)
|
||||
{
|
||||
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
|
||||
write(dynabuf, msg.method);
|
||||
write(dynabuf, msg.method());
|
||||
write(dynabuf, " ");
|
||||
write(dynabuf, msg.url);
|
||||
write(dynabuf, msg.target());
|
||||
switch(msg.version)
|
||||
{
|
||||
case 10:
|
||||
@@ -68,7 +68,7 @@ write_start_line(DynamicBuffer& dynabuf,
|
||||
}
|
||||
write(dynabuf, msg.status);
|
||||
write(dynabuf, " ");
|
||||
write(dynabuf, msg.reason);
|
||||
write(dynabuf, msg.reason());
|
||||
write(dynabuf, "\r\n");
|
||||
}
|
||||
|
||||
@@ -82,6 +82,10 @@ write_fields(DynamicBuffer& dynabuf, FieldSequence const& fields)
|
||||
// "FieldSequence requirements not met");
|
||||
for(auto const& field : fields)
|
||||
{
|
||||
auto const name = field.name();
|
||||
BOOST_ASSERT(! name.empty());
|
||||
if(name[0] == ':')
|
||||
continue;
|
||||
write(dynabuf, field.name());
|
||||
write(dynabuf, ": ");
|
||||
write(dynabuf, field.value());
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <beast/config.hpp>
|
||||
#include <beast/http/fields.hpp>
|
||||
#include <beast/core/detail/integer_sequence.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
@@ -65,17 +66,53 @@ struct header<true, Fields>
|
||||
*/
|
||||
int version;
|
||||
|
||||
/** The Request Method
|
||||
/** Return the Request Method
|
||||
|
||||
@note This field is present only if `isRequest == true`.
|
||||
@note This function is only available if `isRequest == true`.
|
||||
*/
|
||||
std::string method;
|
||||
auto
|
||||
method() const ->
|
||||
decltype(std::declval<Fields>().method()) const
|
||||
{
|
||||
return fields.method();
|
||||
}
|
||||
|
||||
/** The Request URI
|
||||
/** Set the Request Method
|
||||
|
||||
@note This field is present only if `isRequest == true`.
|
||||
@param value A value that represents the request method.
|
||||
|
||||
@note This function is only available if `isRequest == true`.
|
||||
*/
|
||||
std::string url;
|
||||
template<class Value>
|
||||
void
|
||||
method(Value&& value)
|
||||
{
|
||||
fields.method(std::forward<Value>(value));
|
||||
}
|
||||
|
||||
/** Return the Request Target
|
||||
|
||||
@note This function is only available if `isRequest == true`.
|
||||
*/
|
||||
auto
|
||||
target() const ->
|
||||
decltype(std::declval<Fields>().target()) const
|
||||
{
|
||||
return fields.target();
|
||||
}
|
||||
|
||||
/** Set the Request Target
|
||||
|
||||
@param value A value that represents the request method.
|
||||
|
||||
@note This function is only available if `isRequest == true`.
|
||||
*/
|
||||
template<class Value>
|
||||
void
|
||||
target(Value&& value)
|
||||
{
|
||||
fields.target(std::forward<Value>(value));
|
||||
}
|
||||
|
||||
/// The HTTP field values.
|
||||
fields_type fields;
|
||||
@@ -197,17 +234,36 @@ struct header<false, Fields>
|
||||
|
||||
/** The Response Status-Code.
|
||||
|
||||
@note This field is present only if `isRequest == false`.
|
||||
@note This member is only available if `isRequest == false`.
|
||||
*/
|
||||
int status;
|
||||
|
||||
/** The Response Reason-Phrase.
|
||||
/** Return the Reason-Phrase.
|
||||
|
||||
The Reason-Phrase is obsolete as of rfc7230.
|
||||
|
||||
@note This field is present only if `isRequest == false`.
|
||||
@note This function is only available if `isRequest == false`.
|
||||
*/
|
||||
std::string reason;
|
||||
auto
|
||||
reason() const ->
|
||||
decltype(std::declval<Fields>().method()) const
|
||||
{
|
||||
return fields.reason();
|
||||
}
|
||||
|
||||
/** Set the Reason-Phrase
|
||||
|
||||
@param value A value that represents the reason phrase.
|
||||
|
||||
@note This function is only available if `isRequest == false`.
|
||||
*/
|
||||
template<class Value>
|
||||
void
|
||||
reason(Value&& value)
|
||||
{
|
||||
fields.reason(std::forward<Value>(value));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** A container for a complete HTTP message.
|
||||
|
||||
@@ -158,13 +158,11 @@ private:
|
||||
void
|
||||
on_request(
|
||||
boost::string_ref const& method,
|
||||
boost::string_ref const& path,
|
||||
boost::string_ref const& target,
|
||||
int version, error_code&)
|
||||
{
|
||||
m_.url = std::string{
|
||||
path.data(), path.size()};
|
||||
m_.method = std::string{
|
||||
method.data(), method.size()};
|
||||
m_.target(target);
|
||||
m_.method(method);
|
||||
m_.version = version;
|
||||
}
|
||||
|
||||
@@ -174,9 +172,8 @@ private:
|
||||
int version, error_code&)
|
||||
{
|
||||
m_.status = status;
|
||||
m_.reason = std::string{
|
||||
reason.data(), reason.size()};
|
||||
m_.version = version;
|
||||
m_.reason(reason);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in new issue
Block a user