mirror of
https://github.com/boostorg/beast.git
synced 2025-08-02 06:15:24 +02:00
Refactor header status, reason, and target (API Change):
* header::result is a family of functions to replace header::status * header interface now uses status enum and also ints * reason-phrase is no longer stored unless the user explicitly requests it. * When serializing, the standard reason is used for the corresponding status code unless the user has changed it.
This commit is contained in:
@@ -4,6 +4,8 @@ API Changes:
|
|||||||
|
|
||||||
* Refactor method and verb
|
* Refactor method and verb
|
||||||
* Canonicalize string_view parameter types
|
* Canonicalize string_view parameter types
|
||||||
|
* Tidy up empty_body writer error
|
||||||
|
* Refactor header status, reason, and target
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -147,8 +147,7 @@ objects:
|
|||||||
```
|
```
|
||||||
response<string_body> res;
|
response<string_body> res;
|
||||||
res.version = 11; // HTTP/1.1
|
res.version = 11; // HTTP/1.1
|
||||||
res.status = 200;
|
res.result(status::ok);
|
||||||
res.reason("OK");
|
|
||||||
res.body = "Hello, world!";
|
res.body = "Hello, world!";
|
||||||
res.fields.insert("Server", "Beast");
|
res.fields.insert("Server", "Beast");
|
||||||
res.fields.insert("Content-Length", res.body.size());
|
res.fields.insert("Content-Length", res.body.size());
|
||||||
|
@@ -128,8 +128,7 @@ the number of octets received prior to the server closing the connection:
|
|||||||
{
|
{
|
||||||
response<string_body> res;
|
response<string_body> res;
|
||||||
res.version = 11;
|
res.version = 11;
|
||||||
res.status = 200;
|
res.result(status::ok);
|
||||||
res.reason("OK");
|
|
||||||
res.fields.insert("Server", "Beast");
|
res.fields.insert("Server", "Beast");
|
||||||
res.body = "Hello, world!";
|
res.body = "Hello, world!";
|
||||||
|
|
||||||
|
@@ -164,7 +164,7 @@ send_expect_100_continue(
|
|||||||
{
|
{
|
||||||
response<string_body> res;
|
response<string_body> res;
|
||||||
read(stream, buffer, res);
|
read(stream, buffer, res);
|
||||||
if(res.status != 100)
|
if(res.result() != status::continue_)
|
||||||
{
|
{
|
||||||
// The server indicated that it will not
|
// The server indicated that it will not
|
||||||
// accept the request, so skip sending the body.
|
// accept the request, so skip sending the body.
|
||||||
@@ -229,7 +229,7 @@ send_cgi_response(
|
|||||||
// allowing serialization to use manually provided buffers.
|
// allowing serialization to use manually provided buffers.
|
||||||
message<false, buffer_body, fields> res;
|
message<false, buffer_body, fields> res;
|
||||||
|
|
||||||
res.status = 200;
|
res.result(status::ok);
|
||||||
res.version = 11;
|
res.version = 11;
|
||||||
res.fields.insert("Server", "Beast");
|
res.fields.insert("Server", "Beast");
|
||||||
res.fields.insert("Transfer-Encoding", "chunked");
|
res.fields.insert("Transfer-Encoding", "chunked");
|
||||||
|
@@ -197,8 +197,7 @@ receive_expect_100_continue(
|
|||||||
// send 100 response
|
// send 100 response
|
||||||
response<empty_body> res;
|
response<empty_body> res;
|
||||||
res.version = 11;
|
res.version = 11;
|
||||||
res.status = 100;
|
res.result(status::continue_);
|
||||||
res.reason("Continue");
|
|
||||||
res.fields.insert("Server", "test");
|
res.fields.insert("Server", "test");
|
||||||
write(stream, res, ec);
|
write(stream, res, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
|
@@ -56,7 +56,7 @@ class custom_parser
|
|||||||
/// Called after receiving the start-line (isRequest == false).
|
/// Called after receiving the start-line (isRequest == false).
|
||||||
void
|
void
|
||||||
on_response(
|
on_response(
|
||||||
int status, // The status-code
|
int code, // The status-code
|
||||||
string_view reason, // The obsolete reason-phrase
|
string_view reason, // The obsolete reason-phrase
|
||||||
int version, // The HTTP-version
|
int version, // The HTTP-version
|
||||||
error_code& ec); // The error returned to the caller, if any
|
error_code& ec); // The error returned to the caller, if any
|
||||||
|
@@ -256,13 +256,13 @@ struct header<false, Fields>
|
|||||||
string_view
|
string_view
|
||||||
reason() const
|
reason() const
|
||||||
{
|
{
|
||||||
return fields.reason();
|
return fields.reason_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
reason(string_view s)
|
reason(string_view s)
|
||||||
{
|
{
|
||||||
fields.reason(s);
|
fields.reason_impl(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fields fields;
|
Fields fields;
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 37 KiB |
@@ -88,6 +88,7 @@
|
|||||||
<member><link linkend="beast.ref.http__connection">connection</link></member>
|
<member><link linkend="beast.ref.http__connection">connection</link></member>
|
||||||
<member><link linkend="beast.ref.http__error">error</link></member>
|
<member><link linkend="beast.ref.http__error">error</link></member>
|
||||||
<member><link linkend="beast.ref.http__status">status</link></member>
|
<member><link linkend="beast.ref.http__status">status</link></member>
|
||||||
|
<member><link linkend="beast.ref.http__status_class">status_class</link></member>
|
||||||
<member><link linkend="beast.ref.http__verb">verb</link></member>
|
<member><link linkend="beast.ref.http__verb">verb</link></member>
|
||||||
</simplelist>
|
</simplelist>
|
||||||
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
<bridgehead renderas="sect3">Type Traits</bridgehead>
|
||||||
|
@@ -234,8 +234,7 @@ private:
|
|||||||
if(! boost::filesystem::exists(path))
|
if(! boost::filesystem::exists(path))
|
||||||
{
|
{
|
||||||
response<string_body> res;
|
response<string_body> res;
|
||||||
res.status = 404;
|
res.result(status::not_found);
|
||||||
res.reason("Not Found");
|
|
||||||
res.version = req_.version;
|
res.version = req_.version;
|
||||||
res.fields.insert("Server", "http_async_server");
|
res.fields.insert("Server", "http_async_server");
|
||||||
res.fields.insert("Content-Type", "text/html");
|
res.fields.insert("Content-Type", "text/html");
|
||||||
@@ -249,8 +248,7 @@ private:
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
resp_type res;
|
resp_type res;
|
||||||
res.status = 200;
|
res.result(status::ok);
|
||||||
res.reason("OK");
|
|
||||||
res.version = req_.version;
|
res.version = req_.version;
|
||||||
res.fields.insert("Server", "http_async_server");
|
res.fields.insert("Server", "http_async_server");
|
||||||
res.fields.insert("Content-Type", mime_type(path));
|
res.fields.insert("Content-Type", mime_type(path));
|
||||||
@@ -263,8 +261,7 @@ private:
|
|||||||
catch(std::exception const& e)
|
catch(std::exception const& e)
|
||||||
{
|
{
|
||||||
response<string_body> res;
|
response<string_body> res;
|
||||||
res.status = 500;
|
res.result(status::internal_server_error);
|
||||||
res.reason("Internal Error");
|
|
||||||
res.version = req_.version;
|
res.version = req_.version;
|
||||||
res.fields.insert("Server", "http_async_server");
|
res.fields.insert("Server", "http_async_server");
|
||||||
res.fields.insert("Content-Type", "text/html");
|
res.fields.insert("Content-Type", "text/html");
|
||||||
|
@@ -164,8 +164,7 @@ private:
|
|||||||
if(! boost::filesystem::exists(path))
|
if(! boost::filesystem::exists(path))
|
||||||
{
|
{
|
||||||
response<string_body> res;
|
response<string_body> res;
|
||||||
res.status = 404;
|
res.result(status::not_found);
|
||||||
res.reason("Not Found");
|
|
||||||
res.version = req.version;
|
res.version = req.version;
|
||||||
res.fields.insert("Server", "http_sync_server");
|
res.fields.insert("Server", "http_sync_server");
|
||||||
res.fields.insert("Content-Type", "text/html");
|
res.fields.insert("Content-Type", "text/html");
|
||||||
@@ -179,7 +178,7 @@ private:
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
resp_type res;
|
resp_type res;
|
||||||
res.status = 200;
|
res.result(status::ok);
|
||||||
res.reason("OK");
|
res.reason("OK");
|
||||||
res.version = req.version;
|
res.version = req.version;
|
||||||
res.fields.insert("Server", "http_sync_server");
|
res.fields.insert("Server", "http_sync_server");
|
||||||
@@ -193,7 +192,7 @@ private:
|
|||||||
catch(std::exception const& e)
|
catch(std::exception const& e)
|
||||||
{
|
{
|
||||||
response<string_body> res;
|
response<string_body> res;
|
||||||
res.status = 500;
|
res.result(status::internal_server_error);
|
||||||
res.reason("Internal Error");
|
res.reason("Internal Error");
|
||||||
res.version = req.version;
|
res.version = req.version;
|
||||||
res.fields.insert("Server", "http_sync_server");
|
res.fields.insert("Server", "http_sync_server");
|
||||||
|
@@ -286,33 +286,48 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
string_view
|
string_view
|
||||||
method_string() const;
|
method_impl() const
|
||||||
|
{
|
||||||
|
return (*this)[":method"];
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
method_string(string_view s);
|
method_impl(string_view s)
|
||||||
|
{
|
||||||
|
if(s.empty())
|
||||||
|
this->erase(":method");
|
||||||
|
else
|
||||||
|
this->replace(":method", s);
|
||||||
|
}
|
||||||
|
|
||||||
string_view
|
string_view
|
||||||
target() const
|
target_impl() const
|
||||||
{
|
{
|
||||||
return (*this)[":target"];
|
return (*this)[":target"];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
target(string_view s)
|
target_impl(string_view s)
|
||||||
{
|
{
|
||||||
|
if(s.empty())
|
||||||
|
this->erase(":target");
|
||||||
|
else
|
||||||
return this->replace(":target", s);
|
return this->replace(":target", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
string_view
|
string_view
|
||||||
reason() const
|
reason_impl() const
|
||||||
{
|
{
|
||||||
return (*this)[":reason"];
|
return (*this)[":reason"];
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
reason(string_view s)
|
reason_impl(string_view s)
|
||||||
{
|
{
|
||||||
return this->replace(":reason", s);
|
if(s.empty())
|
||||||
|
this->erase(":reason");
|
||||||
|
else
|
||||||
|
this->replace(":reason", s);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -42,6 +42,8 @@ public:
|
|||||||
case error::end_of_stream: return "end of stream";
|
case error::end_of_stream: return "end of stream";
|
||||||
case error::partial_message: return "partial message";
|
case error::partial_message: return "partial message";
|
||||||
case error::need_more: return "need more";
|
case error::need_more: return "need more";
|
||||||
|
case error::unexpected_body: return "unexpected body";
|
||||||
|
case error::need_buffer: return "need buffer";
|
||||||
case error::buffer_overflow: return "buffer overflow";
|
case error::buffer_overflow: return "buffer overflow";
|
||||||
case error::bad_line_ending: return "bad line ending";
|
case error::bad_line_ending: return "bad line ending";
|
||||||
case error::bad_method: return "bad method";
|
case error::bad_method: return "bad method";
|
||||||
|
@@ -230,8 +230,7 @@ erase(string_view name)
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
void
|
void
|
||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
insert(string_view name,
|
insert(string_view name, string_view value)
|
||||||
string_view value)
|
|
||||||
{
|
{
|
||||||
value = detail::trim(value);
|
value = detail::trim(value);
|
||||||
auto const p = alloc_traits::allocate(this->member(), 1);
|
auto const p = alloc_traits::allocate(this->member(), 1);
|
||||||
@@ -243,33 +242,13 @@ insert(string_view name,
|
|||||||
template<class Allocator>
|
template<class Allocator>
|
||||||
void
|
void
|
||||||
basic_fields<Allocator>::
|
basic_fields<Allocator>::
|
||||||
replace(string_view name,
|
replace(string_view name, string_view value)
|
||||||
string_view value)
|
|
||||||
{
|
{
|
||||||
value = detail::trim(value);
|
value = detail::trim(value);
|
||||||
erase(name);
|
erase(name);
|
||||||
insert(name, value);
|
insert(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
string_view
|
|
||||||
basic_fields<Allocator>::
|
|
||||||
method_string() const
|
|
||||||
{
|
|
||||||
return (*this)[":method"];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Allocator>
|
|
||||||
void
|
|
||||||
basic_fields<Allocator>::
|
|
||||||
method_string(string_view s)
|
|
||||||
{
|
|
||||||
if(s.empty())
|
|
||||||
this->erase(":method");
|
|
||||||
else
|
|
||||||
this->replace(":method", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
|
||||||
|
@@ -30,7 +30,7 @@ get_method_string() const
|
|||||||
{
|
{
|
||||||
if(method_ != verb::unknown)
|
if(method_ != verb::unknown)
|
||||||
return to_string(method_);
|
return to_string(method_);
|
||||||
return fields.method_string();
|
return fields.method_impl();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Fields>
|
template<class Fields>
|
||||||
@@ -43,7 +43,7 @@ set_method(verb v)
|
|||||||
BOOST_THROW_EXCEPTION(
|
BOOST_THROW_EXCEPTION(
|
||||||
std::invalid_argument{"unknown verb"});
|
std::invalid_argument{"unknown verb"});
|
||||||
method_ = v;
|
method_ = v;
|
||||||
fields.method_string({});
|
fields.method_impl({});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Fields>
|
template<class Fields>
|
||||||
@@ -54,9 +54,21 @@ set_method(string_view s)
|
|||||||
{
|
{
|
||||||
method_ = string_to_verb(s);
|
method_ = string_to_verb(s);
|
||||||
if(method_ != verb::unknown)
|
if(method_ != verb::unknown)
|
||||||
fields.method_string({});
|
fields.method_impl({});
|
||||||
else
|
else
|
||||||
fields.method_string(s);
|
fields.method_impl(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Fields>
|
||||||
|
template<class>
|
||||||
|
string_view
|
||||||
|
header<false, Fields>::
|
||||||
|
get_reason() const
|
||||||
|
{
|
||||||
|
auto const s = fields.reason_impl();
|
||||||
|
if(! s.empty())
|
||||||
|
return s;
|
||||||
|
return obsolete_reason(result_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Fields>
|
template<class Fields>
|
||||||
@@ -79,8 +91,8 @@ swap(
|
|||||||
{
|
{
|
||||||
using std::swap;
|
using std::swap;
|
||||||
swap(a.version, b.version);
|
swap(a.version, b.version);
|
||||||
swap(a.status, b.status);
|
|
||||||
swap(a.fields, b.fields);
|
swap(a.fields, b.fields);
|
||||||
|
swap(a.result_, b.result_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool isRequest, class Body, class Fields>
|
template<bool isRequest, class Body, class Fields>
|
||||||
@@ -242,9 +254,9 @@ prepare(message<isRequest, Body, Fields>& msg,
|
|||||||
operator()(message<false, Body, Fields>& msg,
|
operator()(message<false, Body, Fields>& msg,
|
||||||
detail::prepare_info const& pi) const
|
detail::prepare_info const& pi) const
|
||||||
{
|
{
|
||||||
if((msg.status / 100 ) != 1 &&
|
if(to_status_class(msg.result()) != status_class::informational &&
|
||||||
msg.status != 204 &&
|
msg.result() != status::no_content &&
|
||||||
msg.status != 304)
|
msg.result() != status::not_modified)
|
||||||
{
|
{
|
||||||
msg.fields.insert(
|
msg.fields.insert(
|
||||||
"Content-Length", *pi.content_length);
|
"Content-Length", *pi.content_length);
|
||||||
|
@@ -23,6 +23,7 @@ void
|
|||||||
write_start_line(std::ostream& os,
|
write_start_line(std::ostream& os,
|
||||||
header<true, Fields> const& msg)
|
header<true, Fields> const& msg)
|
||||||
{
|
{
|
||||||
|
// VFALCO This should all be done without dynamic allocation
|
||||||
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
|
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
|
||||||
os << msg.method() << " " << msg.target();
|
os << msg.method() << " " << msg.target();
|
||||||
switch(msg.version)
|
switch(msg.version)
|
||||||
@@ -37,18 +38,14 @@ void
|
|||||||
write_start_line(std::ostream& os,
|
write_start_line(std::ostream& os,
|
||||||
header<false, Fields> const& msg)
|
header<false, Fields> const& msg)
|
||||||
{
|
{
|
||||||
|
// VFALCO This should all be done without dynamic allocation
|
||||||
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
|
BOOST_ASSERT(msg.version == 10 || msg.version == 11);
|
||||||
switch(msg.version)
|
switch(msg.version)
|
||||||
{
|
{
|
||||||
case 10: os << "HTTP/1.0 "; break;
|
case 10: os << "HTTP/1.0 "; break;
|
||||||
case 11: os << "HTTP/1.1 "; break;
|
case 11: os << "HTTP/1.1 "; break;
|
||||||
}
|
}
|
||||||
auto const reason = msg.reason();
|
os << msg.result_int() << " " << msg.reason() << "\r\n";
|
||||||
if(reason.empty())
|
|
||||||
os << msg.status << " " << msg.reason() << "\r\n";
|
|
||||||
else
|
|
||||||
os << msg.status << " " <<
|
|
||||||
obsolete_reason(static_cast<status>(msg.status)) << "\r\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class FieldSequence>
|
template<class FieldSequence>
|
||||||
|
@@ -8,10 +8,101 @@
|
|||||||
#ifndef BEAST_HTTP_IMPL_STATUS_IPP
|
#ifndef BEAST_HTTP_IMPL_STATUS_IPP
|
||||||
#define BEAST_HTTP_IMPL_STATUS_IPP
|
#define BEAST_HTTP_IMPL_STATUS_IPP
|
||||||
|
|
||||||
|
#include <boost/throw_exception.hpp>
|
||||||
|
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
template<class = void>
|
||||||
|
status
|
||||||
|
int_to_status(int v)
|
||||||
|
{
|
||||||
|
switch(static_cast<status>(v))
|
||||||
|
{
|
||||||
|
// 1xx
|
||||||
|
case status::continue_:
|
||||||
|
case status::switching_protocols:
|
||||||
|
case status::processing:
|
||||||
|
// [[fallthrough]]
|
||||||
|
|
||||||
|
// 2xx
|
||||||
|
case status::ok:
|
||||||
|
case status::created:
|
||||||
|
case status::accepted:
|
||||||
|
case status::non_authoritative_information:
|
||||||
|
case status::no_content:
|
||||||
|
case status::reset_content:
|
||||||
|
case status::partial_content:
|
||||||
|
case status::multi_status:
|
||||||
|
case status::already_reported:
|
||||||
|
case status::im_used:
|
||||||
|
// [[fallthrough]]
|
||||||
|
|
||||||
|
// 3xx
|
||||||
|
case status::multiple_choices:
|
||||||
|
case status::moved_permanently:
|
||||||
|
case status::found:
|
||||||
|
case status::see_other:
|
||||||
|
case status::not_modified:
|
||||||
|
case status::use_proxy:
|
||||||
|
case status::temporary_redirect:
|
||||||
|
case status::permanent_redirect:
|
||||||
|
// [[fallthrough]]
|
||||||
|
|
||||||
|
// 4xx
|
||||||
|
case status::bad_request:
|
||||||
|
case status::unauthorized:
|
||||||
|
case status::payment_required:
|
||||||
|
case status::forbidden:
|
||||||
|
case status::not_found:
|
||||||
|
case status::method_not_allowed:
|
||||||
|
case status::not_acceptable:
|
||||||
|
case status::proxy_authentication_required:
|
||||||
|
case status::request_timeout:
|
||||||
|
case status::conflict:
|
||||||
|
case status::gone:
|
||||||
|
case status::length_required:
|
||||||
|
case status::precondition_failed:
|
||||||
|
case status::payload_too_large:
|
||||||
|
case status::uri_too_long:
|
||||||
|
case status::unsupported_media_type:
|
||||||
|
case status::range_not_satisfiable:
|
||||||
|
case status::expectation_failed:
|
||||||
|
case status::misdirected_request:
|
||||||
|
case status::unprocessable_entity:
|
||||||
|
case status::locked:
|
||||||
|
case status::failed_dependency:
|
||||||
|
case status::upgrade_required:
|
||||||
|
case status::precondition_required:
|
||||||
|
case status::too_many_requests:
|
||||||
|
case status::request_header_fields_too_large:
|
||||||
|
case status::connection_closed_without_response:
|
||||||
|
case status::unavailable_for_legal_reasons:
|
||||||
|
case status::client_closed_request:
|
||||||
|
// [[fallthrough]]
|
||||||
|
|
||||||
|
// 5xx
|
||||||
|
case status::internal_server_error:
|
||||||
|
case status::not_implemented:
|
||||||
|
case status::bad_gateway:
|
||||||
|
case status::service_unavailable:
|
||||||
|
case status::gateway_timeout:
|
||||||
|
case status::http_version_not_supported:
|
||||||
|
case status::variant_also_negotiates:
|
||||||
|
case status::insufficient_storage:
|
||||||
|
case status::loop_detected:
|
||||||
|
case status::not_extended:
|
||||||
|
case status::network_authentication_required:
|
||||||
|
case status::network_connect_timeout_error:
|
||||||
|
return static_cast<status>(v);
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return status::unknown;
|
||||||
|
}
|
||||||
|
|
||||||
template<class = void>
|
template<class = void>
|
||||||
string_view
|
string_view
|
||||||
status_to_string(int v)
|
status_to_string(int v)
|
||||||
@@ -92,11 +183,49 @@ status_to_string(int v)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return "Unknown Status";
|
return "<unknown-status>";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class = void>
|
||||||
|
status_class
|
||||||
|
to_status_class(int v)
|
||||||
|
{
|
||||||
|
switch(v / 100)
|
||||||
|
{
|
||||||
|
case 1: return status_class::informational;
|
||||||
|
case 2: return status_class::successful;
|
||||||
|
case 3: return status_class::redirection;
|
||||||
|
case 4: return status_class::client_error;
|
||||||
|
case 5: return status_class::server_error;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return status_class::unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
|
inline
|
||||||
|
status
|
||||||
|
int_to_status(int v)
|
||||||
|
{
|
||||||
|
return detail::int_to_status(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
status_class
|
||||||
|
to_status_class(int v)
|
||||||
|
{
|
||||||
|
return detail::to_status_class(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
status_class
|
||||||
|
to_status_class(status v)
|
||||||
|
{
|
||||||
|
return to_status_class(static_cast<int>(v));
|
||||||
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
string_view
|
string_view
|
||||||
obsolete_reason(status v)
|
obsolete_reason(status v)
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#include <beast/config.hpp>
|
#include <beast/config.hpp>
|
||||||
#include <beast/http/fields.hpp>
|
#include <beast/http/fields.hpp>
|
||||||
#include <beast/http/verb.hpp>
|
#include <beast/http/verb.hpp>
|
||||||
|
#include <beast/http/status.hpp>
|
||||||
#include <beast/core/string_view.hpp>
|
#include <beast/core/string_view.hpp>
|
||||||
#include <beast/core/detail/integer_sequence.hpp>
|
#include <beast/core/detail/integer_sequence.hpp>
|
||||||
#include <boost/throw_exception.hpp>
|
#include <boost/throw_exception.hpp>
|
||||||
@@ -58,104 +59,6 @@ struct header<true, Fields>
|
|||||||
/// The type representing the fields.
|
/// The type representing the fields.
|
||||||
using fields_type = Fields;
|
using fields_type = Fields;
|
||||||
|
|
||||||
/** The HTTP version.
|
|
||||||
|
|
||||||
This holds both the major and minor version numbers,
|
|
||||||
using these formulas:
|
|
||||||
@code
|
|
||||||
major = version / 10;
|
|
||||||
minor = version % 10;
|
|
||||||
@endcode
|
|
||||||
*/
|
|
||||||
int version;
|
|
||||||
|
|
||||||
/** Return the request-method verb.
|
|
||||||
|
|
||||||
If the request-method is not one of the recognized verbs,
|
|
||||||
@ref verb::unknown is returned. Callers may use @ref method_string
|
|
||||||
to retrieve the exact text.
|
|
||||||
|
|
||||||
@note This function is only available if `isRequest == true`.
|
|
||||||
|
|
||||||
@see @ref method_string
|
|
||||||
*/
|
|
||||||
verb
|
|
||||||
method() const
|
|
||||||
{
|
|
||||||
return method_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the request-method verb.
|
|
||||||
|
|
||||||
This function will set the method for requests to one
|
|
||||||
of the known verbs.
|
|
||||||
|
|
||||||
@param v The request method verb to set.
|
|
||||||
This may not be @ref verb::unknown.
|
|
||||||
|
|
||||||
@throw std::invalid_argument when `v == verb::unknown`.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
method(verb v)
|
|
||||||
{
|
|
||||||
set_method(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the request-method as a string.
|
|
||||||
|
|
||||||
@note This function is only available if `isRequest == true`.
|
|
||||||
|
|
||||||
@see @ref method
|
|
||||||
*/
|
|
||||||
string_view
|
|
||||||
method_string() const
|
|
||||||
{
|
|
||||||
return get_method_string();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the request-method using a string.
|
|
||||||
|
|
||||||
This function will set the method for requests to a verb
|
|
||||||
if the string matches a known verb, otherwise it will
|
|
||||||
store a copy of the passed string as the method.
|
|
||||||
|
|
||||||
@param s A string representing the request method.
|
|
||||||
|
|
||||||
@note This function is only available if `isRequest == true`.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
method(string_view s)
|
|
||||||
{
|
|
||||||
set_method(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 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;
|
|
||||||
|
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
header() = default;
|
header() = default;
|
||||||
|
|
||||||
@@ -198,13 +101,106 @@ struct header<true, Fields>
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The HTTP-version.
|
||||||
|
|
||||||
|
This holds both the major and minor version numbers,
|
||||||
|
using these formulas:
|
||||||
|
@code
|
||||||
|
int major = version / 10;
|
||||||
|
int minor = version % 10;
|
||||||
|
@endcode
|
||||||
|
*/
|
||||||
|
int version;
|
||||||
|
|
||||||
|
/// The HTTP field values.
|
||||||
|
fields_type fields;
|
||||||
|
|
||||||
|
/** Return the request-method verb.
|
||||||
|
|
||||||
|
If the request-method is not one of the recognized verbs,
|
||||||
|
@ref verb::unknown is returned. Callers may use @ref method_string
|
||||||
|
to retrieve the exact text.
|
||||||
|
|
||||||
|
@note This function is only available if `isRequest == true`.
|
||||||
|
|
||||||
|
@see @ref method_string
|
||||||
|
*/
|
||||||
|
verb
|
||||||
|
method() const
|
||||||
|
{
|
||||||
|
return method_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the request-method verb.
|
||||||
|
|
||||||
|
This function will set the method for requests to a known verb.
|
||||||
|
|
||||||
|
@param v The request method verb to set.
|
||||||
|
This may not be @ref verb::unknown.
|
||||||
|
|
||||||
|
@throw std::invalid_argument when `v == verb::unknown`.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
method(verb v)
|
||||||
|
{
|
||||||
|
set_method(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the request-method string.
|
||||||
|
|
||||||
|
@note This function is only available if `isRequest == true`.
|
||||||
|
|
||||||
|
@see @ref method
|
||||||
|
*/
|
||||||
|
string_view
|
||||||
|
method_string() const
|
||||||
|
{
|
||||||
|
return get_method_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the request-method string.
|
||||||
|
|
||||||
|
This function will set the method for requests to a verb
|
||||||
|
if the string matches a known verb, otherwise it will
|
||||||
|
store a copy of the passed string as the method.
|
||||||
|
|
||||||
|
@param s A string representing the request-method.
|
||||||
|
|
||||||
|
@note This function is only available if `isRequest == true`.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
method(string_view s)
|
||||||
|
{
|
||||||
|
set_method(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the request-target string.
|
||||||
|
|
||||||
|
@note This function is only available if `isRequest == true`.
|
||||||
|
*/
|
||||||
|
string_view
|
||||||
|
target() const
|
||||||
|
{
|
||||||
|
return fields.target_impl();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the request-target string.
|
||||||
|
|
||||||
|
@param s A string representing the request-target.
|
||||||
|
|
||||||
|
@note This function is only available if `isRequest == true`.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
target(string_view s)
|
||||||
|
{
|
||||||
|
fields.target_impl(s);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template<class Fields>
|
template<class T>
|
||||||
friend
|
friend
|
||||||
void
|
void
|
||||||
swap(
|
swap(header<true, T>& m1, header<true, T>& m2);
|
||||||
header<true, Fields>& m1,
|
|
||||||
header<true, Fields>& m2);
|
|
||||||
|
|
||||||
template<class = void>
|
template<class = void>
|
||||||
string_view
|
string_view
|
||||||
@@ -256,7 +252,7 @@ struct header<false, Fields>
|
|||||||
/// The HTTP field values.
|
/// The HTTP field values.
|
||||||
fields_type fields;
|
fields_type fields;
|
||||||
|
|
||||||
/// Default constructor
|
/// Default constructor.
|
||||||
header() = default;
|
header() = default;
|
||||||
|
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
@@ -293,11 +289,62 @@ struct header<false, Fields>
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** The Response Status-Code.
|
/** The response status-code result.
|
||||||
|
|
||||||
|
If the actual status code is not a known code, this
|
||||||
|
function returns @ref status::unknown. Use @ref result_int
|
||||||
|
to return the raw status code as a number.
|
||||||
|
|
||||||
@note This member is only available if `isRequest == false`.
|
@note This member is only available if `isRequest == false`.
|
||||||
*/
|
*/
|
||||||
int status;
|
status
|
||||||
|
result() const
|
||||||
|
{
|
||||||
|
return int_to_status(
|
||||||
|
static_cast<int>(result_));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the response status-code result.
|
||||||
|
|
||||||
|
@param v The code to set.
|
||||||
|
|
||||||
|
@note This member is only available if `isRequest == false`.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
result(status v)
|
||||||
|
{
|
||||||
|
result_ = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set the raw status-code result as an integer.
|
||||||
|
|
||||||
|
This sets the status code to the exact number passed in.
|
||||||
|
If the number does not correspond to one of the known
|
||||||
|
status codes, the function @ref result will return
|
||||||
|
@ref status::unknown. Use @ref result_int to obtain the
|
||||||
|
original raw status-code.
|
||||||
|
|
||||||
|
@param v The status-code integer to set.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
result(int v)
|
||||||
|
{
|
||||||
|
result_ = static_cast<status>(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The response status-code result expressed as an integer.
|
||||||
|
|
||||||
|
This returns the raw status code as an integer, even
|
||||||
|
when that code is not in the list of known status codes.
|
||||||
|
|
||||||
|
@note This member is only available if `isRequest == false`.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
result_int() const
|
||||||
|
{
|
||||||
|
return static_cast<int>(result_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Return the Reason-Phrase.
|
/** Return the Reason-Phrase.
|
||||||
|
|
||||||
@@ -305,26 +352,47 @@ struct header<false, Fields>
|
|||||||
|
|
||||||
@note This function is only available if `isRequest == false`.
|
@note This function is only available if `isRequest == false`.
|
||||||
*/
|
*/
|
||||||
auto
|
string_view
|
||||||
reason() const ->
|
reason() const
|
||||||
decltype(std::declval<Fields>().reason()) const
|
|
||||||
{
|
{
|
||||||
return fields.reason();
|
return get_reason();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the Reason-Phrase
|
/** Set the Reason-Phrase
|
||||||
|
|
||||||
|
This function sets a custom reason-phrase to a copy of
|
||||||
|
the string passed in. Normally it is not necessary to set
|
||||||
|
the reason phrase on an outgoing response object; the
|
||||||
|
implementation will automatically use the standard reason
|
||||||
|
text for the corresponding status code.
|
||||||
|
|
||||||
|
To clear a previously set custom phrase, pass an empty
|
||||||
|
string. This will restore the default standard reason text
|
||||||
|
based on the status code used when serializing.
|
||||||
|
|
||||||
|
The Reason-Phrase is obsolete as of rfc7230.
|
||||||
|
|
||||||
@param value A value that represents the reason phrase.
|
@param value A value that represents the reason phrase.
|
||||||
|
|
||||||
@note This function is only available if `isRequest == false`.
|
@note This function is only available if `isRequest == false`.
|
||||||
*/
|
*/
|
||||||
template<class Value>
|
|
||||||
void
|
void
|
||||||
reason(Value&& value)
|
reason(string_view s)
|
||||||
{
|
{
|
||||||
fields.reason(std::forward<Value>(value));
|
fields.reason_impl(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<class T>
|
||||||
|
friend
|
||||||
|
void
|
||||||
|
swap(header<false, T>& m1, header<false, T>& m2);
|
||||||
|
|
||||||
|
template<class = void>
|
||||||
|
string_view
|
||||||
|
get_reason() const;
|
||||||
|
|
||||||
|
status result_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A container for a complete HTTP message.
|
/** A container for a complete HTTP message.
|
||||||
|
@@ -153,10 +153,10 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_response(int status, string_view reason,
|
on_response(int code, string_view reason,
|
||||||
int version, error_code&)
|
int version, error_code&)
|
||||||
{
|
{
|
||||||
h_.status = status;
|
h_.result(code);
|
||||||
h_.version = version;
|
h_.version = version;
|
||||||
h_.reason(reason);
|
h_.reason(reason);
|
||||||
}
|
}
|
||||||
@@ -341,11 +341,11 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_response(int status,
|
on_response(int code,
|
||||||
string_view reason,
|
string_view reason,
|
||||||
int version, error_code&)
|
int version, error_code&)
|
||||||
{
|
{
|
||||||
m_.status = status;
|
m_.result(code);
|
||||||
m_.version = version;
|
m_.version = version;
|
||||||
m_.reason(reason);
|
m_.reason(reason);
|
||||||
}
|
}
|
||||||
|
@@ -15,8 +15,17 @@
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
enum class status : int
|
enum class status : unsigned short
|
||||||
{
|
{
|
||||||
|
/** An unknown status-code.
|
||||||
|
|
||||||
|
This value indicates that the value for the status code
|
||||||
|
is not in the list of commonly recognized status codes.
|
||||||
|
Callers interested in the exactly value should use the
|
||||||
|
interface which provides the raw integer.
|
||||||
|
*/
|
||||||
|
unknown = 0,
|
||||||
|
|
||||||
continue_ = 100,
|
continue_ = 100,
|
||||||
switching_protocols = 101,
|
switching_protocols = 101,
|
||||||
processing = 102,
|
processing = 102,
|
||||||
@@ -85,13 +94,66 @@ enum class status : int
|
|||||||
network_connect_timeout_error = 599
|
network_connect_timeout_error = 599
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Returns the obsolete reason-phrase text for a status code.
|
/** Represents the class of a status-code.
|
||||||
|
*/
|
||||||
|
enum class status_class : int
|
||||||
|
{
|
||||||
|
/// Unknown status-class
|
||||||
|
unknown = 0,
|
||||||
|
|
||||||
|
/// The request was received, continuing processing.
|
||||||
|
informational = 1,
|
||||||
|
|
||||||
|
/// The request was successfully received, understood, and accepted.
|
||||||
|
successful = 2,
|
||||||
|
|
||||||
|
/// Further action needs to be taken in order to complete the request.
|
||||||
|
redirection = 3,
|
||||||
|
|
||||||
|
/// The request contains bad syntax or cannot be fulfilled.
|
||||||
|
client_error = 4,
|
||||||
|
|
||||||
|
/// The server failed to fulfill an apparently valid request.
|
||||||
|
server_error = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Converts the integer to a known status-code.
|
||||||
|
|
||||||
|
If the integer does not match a known status code,
|
||||||
|
@ref status::unknown is returned.
|
||||||
|
*/
|
||||||
|
status
|
||||||
|
int_to_status(int v);
|
||||||
|
|
||||||
|
/** Convert an integer to a status_class.
|
||||||
|
|
||||||
|
@param v The integer representing a status code.
|
||||||
|
|
||||||
|
@return The status class. If the integer does not match
|
||||||
|
a known status class, @ref status_class::unknown is returned.
|
||||||
|
*/
|
||||||
|
status_class
|
||||||
|
to_status_class(int v);
|
||||||
|
|
||||||
|
/** Convert a status_code to a status_class.
|
||||||
|
|
||||||
|
@param v The status code to convert.
|
||||||
|
|
||||||
|
@return The status class.
|
||||||
|
*/
|
||||||
|
status_class
|
||||||
|
to_status_class(status v);
|
||||||
|
|
||||||
|
/** Returns the obsolete reason-phrase text for a status code.
|
||||||
|
|
||||||
|
@param v The status code to use.
|
||||||
|
*/
|
||||||
string_view
|
string_view
|
||||||
obsolete_reason(status v);
|
obsolete_reason(status v);
|
||||||
|
|
||||||
/// Outputs the reason phrase of a status code to a stream.
|
/// Outputs the standard reason phrase of a status code to a stream.
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<<(std::ostream& os, status v);
|
operator<<(std::ostream&, status);
|
||||||
|
|
||||||
} // http
|
} // http
|
||||||
} // beast
|
} // beast
|
||||||
|
@@ -128,7 +128,7 @@ enum class verb
|
|||||||
/** Converts a string to the request method verb.
|
/** Converts a string to the request method verb.
|
||||||
|
|
||||||
If the string does not match a known request method,
|
If the string does not match a known request method,
|
||||||
`boost::none` is returned.
|
@ref verb::unknown is returned.
|
||||||
*/
|
*/
|
||||||
verb
|
verb
|
||||||
string_to_verb(string_view s);
|
string_to_verb(string_view s);
|
||||||
|
@@ -148,7 +148,8 @@ operator()(error_code ec, bool again)
|
|||||||
// sent response
|
// sent response
|
||||||
case 1:
|
case 1:
|
||||||
d.state = 99;
|
d.state = 99;
|
||||||
if(d.res.status != 101)
|
if(d.res.result() !=
|
||||||
|
http::status::switching_protocols)
|
||||||
ec = error::handshake_failed;
|
ec = error::handshake_failed;
|
||||||
if(! ec)
|
if(! ec)
|
||||||
{
|
{
|
||||||
|
@@ -112,7 +112,7 @@ do_accept(http::header<true, Fields> const& req,
|
|||||||
http::write(stream_, res, ec);
|
http::write(stream_, res, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
if(res.status != 101)
|
if(res.result() != http::status::switching_protocols)
|
||||||
{
|
{
|
||||||
ec = error::handshake_failed;
|
ec = error::handshake_failed;
|
||||||
// VFALCO TODO Respect keep alive setting, perform
|
// VFALCO TODO Respect keep alive setting, perform
|
||||||
@@ -216,7 +216,7 @@ build_response(http::header<true, Fields> const& req,
|
|||||||
[&](std::string const& text)
|
[&](std::string const& text)
|
||||||
{
|
{
|
||||||
response_type res;
|
response_type res;
|
||||||
res.status = 400;
|
res.result(http::status::bad_request);
|
||||||
res.version = req.version;
|
res.version = req.version;
|
||||||
res.body = text;
|
res.body = text;
|
||||||
prepare(res);
|
prepare(res);
|
||||||
@@ -246,7 +246,7 @@ build_response(http::header<true, Fields> const& req,
|
|||||||
if(version != "13")
|
if(version != "13")
|
||||||
{
|
{
|
||||||
response_type res;
|
response_type res;
|
||||||
res.status = 426;
|
res.result(http::status::upgrade_required);
|
||||||
res.version = req.version;
|
res.version = req.version;
|
||||||
res.fields.insert("Sec-WebSocket-Version", "13");
|
res.fields.insert("Sec-WebSocket-Version", "13");
|
||||||
prepare(res);
|
prepare(res);
|
||||||
@@ -263,7 +263,7 @@ build_response(http::header<true, Fields> const& req,
|
|||||||
pmd_negotiate(
|
pmd_negotiate(
|
||||||
res.fields, unused, offer, pmd_opts_);
|
res.fields, unused, offer, pmd_opts_);
|
||||||
}
|
}
|
||||||
res.status = 101;
|
res.result(http::status::switching_protocols);
|
||||||
res.version = req.version;
|
res.version = req.version;
|
||||||
res.fields.insert("Upgrade", "websocket");
|
res.fields.insert("Upgrade", "websocket");
|
||||||
res.fields.insert("Connection", "upgrade");
|
res.fields.insert("Connection", "upgrade");
|
||||||
@@ -286,7 +286,7 @@ do_response(http::header<false> const& res,
|
|||||||
{
|
{
|
||||||
if(res.version < 11)
|
if(res.version < 11)
|
||||||
return false;
|
return false;
|
||||||
if(res.status != 101)
|
if(res.result() != http::status::switching_protocols)
|
||||||
return false;
|
return false;
|
||||||
if(! is_upgrade(res))
|
if(! is_upgrade(res))
|
||||||
return false;
|
return false;
|
||||||
|
@@ -46,7 +46,7 @@ class custom_parser
|
|||||||
/// Called after receiving the start-line (isRequest == false).
|
/// Called after receiving the start-line (isRequest == false).
|
||||||
void
|
void
|
||||||
on_response(
|
on_response(
|
||||||
int status, // The status-code
|
int code, // The status-code
|
||||||
string_view reason, // The obsolete reason-phrase
|
string_view reason, // The obsolete reason-phrase
|
||||||
int version, // The HTTP-version
|
int version, // The HTTP-version
|
||||||
error_code& ec); // The error returned to the caller, if any
|
error_code& ec); // The error returned to the caller, if any
|
||||||
@@ -238,7 +238,7 @@ public:
|
|||||||
read(stream, buffer, res, ec);
|
read(stream, buffer, res, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
if(res.status != 100)
|
if(res.result() != status::continue_)
|
||||||
{
|
{
|
||||||
// The server indicated that it will not
|
// The server indicated that it will not
|
||||||
// accept the request, so skip sending the body.
|
// accept the request, so skip sending the body.
|
||||||
@@ -291,8 +291,7 @@ public:
|
|||||||
// send 100 response
|
// send 100 response
|
||||||
response<empty_body> res;
|
response<empty_body> res;
|
||||||
res.version = 11;
|
res.version = 11;
|
||||||
res.status = 100;
|
res.result(status::continue_);
|
||||||
res.reason("Continue");
|
|
||||||
res.fields.insert("Server", "test");
|
res.fields.insert("Server", "test");
|
||||||
write(stream, res, ec);
|
write(stream, res, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
@@ -383,7 +382,7 @@ public:
|
|||||||
// allowing serialization to use manually provided buffers.
|
// allowing serialization to use manually provided buffers.
|
||||||
message<false, buffer_body, fields> res;
|
message<false, buffer_body, fields> res;
|
||||||
|
|
||||||
res.status = 200;
|
res.result(status::ok);
|
||||||
res.version = 11;
|
res.version = 11;
|
||||||
res.fields.insert("Server", "Beast");
|
res.fields.insert("Server", "Beast");
|
||||||
res.fields.insert("Transfer-Encoding", "chunked");
|
res.fields.insert("Transfer-Encoding", "chunked");
|
||||||
|
@@ -103,12 +103,12 @@ public:
|
|||||||
testMethodString()
|
testMethodString()
|
||||||
{
|
{
|
||||||
f_t f;
|
f_t f;
|
||||||
f.method_string("CRY");
|
f.method_impl("CRY");
|
||||||
BEAST_EXPECTS(f.method_string() == "CRY", f.method_string());
|
BEAST_EXPECTS(f.method_impl() == "CRY", f.method_impl());
|
||||||
f.method_string("PUT");
|
f.method_impl("PUT");
|
||||||
BEAST_EXPECTS(f.method_string() == "PUT", f.method_string());
|
BEAST_EXPECTS(f.method_impl() == "PUT", f.method_impl());
|
||||||
f.method_string({});
|
f.method_impl({});
|
||||||
BEAST_EXPECTS(f.method_string().empty(), f.method_string());
|
BEAST_EXPECTS(f.method_impl().empty(), f.method_impl());
|
||||||
}
|
}
|
||||||
|
|
||||||
void run() override
|
void run() override
|
||||||
|
@@ -262,19 +262,20 @@ public:
|
|||||||
{
|
{
|
||||||
message<false, string_body, fields> m1;
|
message<false, string_body, fields> m1;
|
||||||
message<false, string_body, fields> m2;
|
message<false, string_body, fields> m2;
|
||||||
m1.status = 200;
|
m1.result(status::ok);
|
||||||
m1.version = 10;
|
m1.version = 10;
|
||||||
m1.body = "1";
|
m1.body = "1";
|
||||||
m1.fields.insert("h", "v");
|
m1.fields.insert("h", "v");
|
||||||
m2.status = 404;
|
m2.result(status::not_found);
|
||||||
m2.reason("OK");
|
|
||||||
m2.body = "2";
|
m2.body = "2";
|
||||||
m2.version = 11;
|
m2.version = 11;
|
||||||
swap(m1, m2);
|
swap(m1, m2);
|
||||||
BEAST_EXPECT(m1.status == 404);
|
BEAST_EXPECT(m1.result() == status::not_found);
|
||||||
BEAST_EXPECT(m2.status == 200);
|
BEAST_EXPECT(m1.result_int() == 404);
|
||||||
BEAST_EXPECT(m1.reason() == "OK");
|
BEAST_EXPECT(m2.result() == status::ok);
|
||||||
BEAST_EXPECT(m2.reason().empty());
|
BEAST_EXPECT(m2.result_int() == 200);
|
||||||
|
BEAST_EXPECT(m1.reason() == "Not Found");
|
||||||
|
BEAST_EXPECT(m2.reason() == "OK");
|
||||||
BEAST_EXPECT(m1.version == 11);
|
BEAST_EXPECT(m1.version == 11);
|
||||||
BEAST_EXPECT(m2.version == 10);
|
BEAST_EXPECT(m2.version == 10);
|
||||||
BEAST_EXPECT(m1.body == "2");
|
BEAST_EXPECT(m1.body == "2");
|
||||||
@@ -321,6 +322,35 @@ public:
|
|||||||
scheck("XYZ");
|
scheck("XYZ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testStatus()
|
||||||
|
{
|
||||||
|
header<false> h;
|
||||||
|
h.result(200);
|
||||||
|
BEAST_EXPECT(h.result_int() == 200);
|
||||||
|
BEAST_EXPECT(h.result() == status::ok);
|
||||||
|
h.result(status::switching_protocols);
|
||||||
|
BEAST_EXPECT(h.result_int() == 101);
|
||||||
|
BEAST_EXPECT(h.result() == status::switching_protocols);
|
||||||
|
h.result(1);
|
||||||
|
BEAST_EXPECT(h.result_int() == 1);
|
||||||
|
BEAST_EXPECT(h.result() == status::unknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
testReason()
|
||||||
|
{
|
||||||
|
header<false> h;
|
||||||
|
h.result(status::ok);
|
||||||
|
BEAST_EXPECT(h.reason() == "OK");
|
||||||
|
h.reason("Pepe");
|
||||||
|
BEAST_EXPECT(h.reason() == "Pepe");
|
||||||
|
h.result(status::not_found);
|
||||||
|
BEAST_EXPECT(h.reason() == "Pepe");
|
||||||
|
h.reason({});
|
||||||
|
BEAST_EXPECT(h.reason() == "Not Found");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
@@ -331,6 +361,8 @@ public:
|
|||||||
testSwap();
|
testSwap();
|
||||||
testSpecialMembers();
|
testSpecialMembers();
|
||||||
testMethod();
|
testMethod();
|
||||||
|
testStatus();
|
||||||
|
testReason();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -182,7 +182,7 @@ public:
|
|||||||
BEAST_EXPECT(p.need_eof());
|
BEAST_EXPECT(p.need_eof());
|
||||||
BEAST_EXPECT(p.content_length() == boost::none);
|
BEAST_EXPECT(p.content_length() == boost::none);
|
||||||
BEAST_EXPECT(m.version == 10);
|
BEAST_EXPECT(m.version == 10);
|
||||||
BEAST_EXPECT(m.status == 200);
|
BEAST_EXPECT(m.result() == status::ok);
|
||||||
BEAST_EXPECT(m.reason() == "OK");
|
BEAST_EXPECT(m.reason() == "OK");
|
||||||
BEAST_EXPECT(m.fields["Server"] == "test");
|
BEAST_EXPECT(m.fields["Server"] == "test");
|
||||||
BEAST_EXPECT(m.body == "Hello, world!");
|
BEAST_EXPECT(m.body == "Hello, world!");
|
||||||
@@ -209,7 +209,7 @@ public:
|
|||||||
BEAST_EXPECT(p.is_chunked());
|
BEAST_EXPECT(p.is_chunked());
|
||||||
BEAST_EXPECT(p.content_length() == boost::none);
|
BEAST_EXPECT(p.content_length() == boost::none);
|
||||||
BEAST_EXPECT(m.version == 11);
|
BEAST_EXPECT(m.version == 11);
|
||||||
BEAST_EXPECT(m.status == 200);
|
BEAST_EXPECT(m.result() == status::ok);
|
||||||
BEAST_EXPECT(m.reason() == "OK");
|
BEAST_EXPECT(m.reason() == "OK");
|
||||||
BEAST_EXPECT(m.fields["Server"] == "test");
|
BEAST_EXPECT(m.fields["Server"] == "test");
|
||||||
BEAST_EXPECT(m.fields["Transfer-Encoding"] == "chunked");
|
BEAST_EXPECT(m.fields["Transfer-Encoding"] == "chunked");
|
||||||
|
@@ -20,6 +20,82 @@ public:
|
|||||||
void
|
void
|
||||||
testStatus()
|
testStatus()
|
||||||
{
|
{
|
||||||
|
auto const check = [&](status s, int i, status_class sc)
|
||||||
|
{
|
||||||
|
BEAST_EXPECT(int_to_status(i) == s);
|
||||||
|
BEAST_EXPECT(to_status_class(i) == sc);
|
||||||
|
BEAST_EXPECT(to_status_class(int_to_status(i)) == sc);
|
||||||
|
};
|
||||||
|
check(status::continue_ ,100, status_class::informational);
|
||||||
|
check(status::switching_protocols ,101, status_class::informational);
|
||||||
|
check(status::processing ,102, status_class::informational);
|
||||||
|
|
||||||
|
check(status::ok ,200, status_class::successful);
|
||||||
|
check(status::created ,201, status_class::successful);
|
||||||
|
check(status::accepted ,202, status_class::successful);
|
||||||
|
check(status::non_authoritative_information ,203, status_class::successful);
|
||||||
|
check(status::no_content ,204, status_class::successful);
|
||||||
|
check(status::reset_content ,205, status_class::successful);
|
||||||
|
check(status::partial_content ,206, status_class::successful);
|
||||||
|
check(status::multi_status ,207, status_class::successful);
|
||||||
|
check(status::already_reported ,208, status_class::successful);
|
||||||
|
check(status::im_used ,226, status_class::successful);
|
||||||
|
|
||||||
|
check(status::multiple_choices ,300, status_class::redirection);
|
||||||
|
check(status::moved_permanently ,301, status_class::redirection);
|
||||||
|
check(status::found ,302, status_class::redirection);
|
||||||
|
check(status::see_other ,303, status_class::redirection);
|
||||||
|
check(status::not_modified ,304, status_class::redirection);
|
||||||
|
check(status::use_proxy ,305, status_class::redirection);
|
||||||
|
check(status::temporary_redirect ,307, status_class::redirection);
|
||||||
|
check(status::permanent_redirect ,308, status_class::redirection);
|
||||||
|
|
||||||
|
check(status::bad_request ,400, status_class::client_error);
|
||||||
|
check(status::unauthorized ,401, status_class::client_error);
|
||||||
|
check(status::payment_required ,402, status_class::client_error);
|
||||||
|
check(status::forbidden ,403, status_class::client_error);
|
||||||
|
check(status::not_found ,404, status_class::client_error);
|
||||||
|
check(status::method_not_allowed ,405, status_class::client_error);
|
||||||
|
check(status::not_acceptable ,406, status_class::client_error);
|
||||||
|
check(status::proxy_authentication_required ,407, status_class::client_error);
|
||||||
|
check(status::request_timeout ,408, status_class::client_error);
|
||||||
|
check(status::conflict ,409, status_class::client_error);
|
||||||
|
check(status::gone ,410, status_class::client_error);
|
||||||
|
check(status::length_required ,411, status_class::client_error);
|
||||||
|
check(status::precondition_failed ,412, status_class::client_error);
|
||||||
|
check(status::payload_too_large ,413, status_class::client_error);
|
||||||
|
check(status::uri_too_long ,414, status_class::client_error);
|
||||||
|
check(status::unsupported_media_type ,415, status_class::client_error);
|
||||||
|
check(status::range_not_satisfiable ,416, status_class::client_error);
|
||||||
|
check(status::expectation_failed ,417, status_class::client_error);
|
||||||
|
check(status::misdirected_request ,421, status_class::client_error);
|
||||||
|
check(status::unprocessable_entity ,422, status_class::client_error);
|
||||||
|
check(status::locked ,423, status_class::client_error);
|
||||||
|
check(status::failed_dependency ,424, status_class::client_error);
|
||||||
|
check(status::upgrade_required ,426, status_class::client_error);
|
||||||
|
check(status::precondition_required ,428, status_class::client_error);
|
||||||
|
check(status::too_many_requests ,429, status_class::client_error);
|
||||||
|
check(status::request_header_fields_too_large ,431, status_class::client_error);
|
||||||
|
check(status::connection_closed_without_response ,444, status_class::client_error);
|
||||||
|
check(status::unavailable_for_legal_reasons ,451, status_class::client_error);
|
||||||
|
check(status::client_closed_request ,499, status_class::client_error);
|
||||||
|
|
||||||
|
check(status::internal_server_error ,500, status_class::server_error);
|
||||||
|
check(status::not_implemented ,501, status_class::server_error);
|
||||||
|
check(status::bad_gateway ,502, status_class::server_error);
|
||||||
|
check(status::service_unavailable ,503, status_class::server_error);
|
||||||
|
check(status::gateway_timeout ,504, status_class::server_error);
|
||||||
|
check(status::http_version_not_supported ,505, status_class::server_error);
|
||||||
|
check(status::variant_also_negotiates ,506, status_class::server_error);
|
||||||
|
check(status::insufficient_storage ,507, status_class::server_error);
|
||||||
|
check(status::loop_detected ,508, status_class::server_error);
|
||||||
|
check(status::not_extended ,510, status_class::server_error);
|
||||||
|
check(status::network_authentication_required ,511, status_class::server_error);
|
||||||
|
check(status::network_connect_timeout_error ,599, status_class::server_error);
|
||||||
|
|
||||||
|
BEAST_EXPECT(to_status_class(1) == status_class::unknown);
|
||||||
|
BEAST_EXPECT(to_status_class(status::unknown) == status_class::unknown);
|
||||||
|
|
||||||
auto const good =
|
auto const good =
|
||||||
[&](status v)
|
[&](status v)
|
||||||
{
|
{
|
||||||
|
@@ -62,11 +62,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_response(int status_,
|
on_response(int code,
|
||||||
string_view reason_,
|
string_view reason_,
|
||||||
int version_, error_code& ec)
|
int version_, error_code& ec)
|
||||||
{
|
{
|
||||||
status = status_;
|
status = code;
|
||||||
reason = std::string(
|
reason = std::string(
|
||||||
reason_.data(), reason_.size());
|
reason_.data(), reason_.size());
|
||||||
version = version_;
|
version = version_;
|
||||||
|
@@ -292,7 +292,7 @@ public:
|
|||||||
{
|
{
|
||||||
message<false, string_body, fields> m;
|
message<false, string_body, fields> m;
|
||||||
m.version = 10;
|
m.version = 10;
|
||||||
m.status = 200;
|
m.result(status::ok);
|
||||||
m.reason("OK");
|
m.reason("OK");
|
||||||
m.fields.insert("Server", "test");
|
m.fields.insert("Server", "test");
|
||||||
m.fields.insert("Content-Length", "5");
|
m.fields.insert("Content-Length", "5");
|
||||||
@@ -311,7 +311,7 @@ public:
|
|||||||
{
|
{
|
||||||
message<false, string_body, fields> m;
|
message<false, string_body, fields> m;
|
||||||
m.version = 11;
|
m.version = 11;
|
||||||
m.status = 200;
|
m.result(status::ok);
|
||||||
m.reason("OK");
|
m.reason("OK");
|
||||||
m.fields.insert("Server", "test");
|
m.fields.insert("Server", "test");
|
||||||
m.fields.insert("Transfer-Encoding", "chunked");
|
m.fields.insert("Transfer-Encoding", "chunked");
|
||||||
@@ -786,7 +786,7 @@ public:
|
|||||||
|
|
||||||
message<false, Body, fields> m0;
|
message<false, Body, fields> m0;
|
||||||
m0.version = 11;
|
m0.version = 11;
|
||||||
m0.status = 200;
|
m0.result(status::ok);
|
||||||
m0.reason("OK");
|
m0.reason("OK");
|
||||||
m0.fields.insert("Server", "test");
|
m0.fields.insert("Server", "test");
|
||||||
m0.body.s = "Hello, world!\n";
|
m0.body.s = "Hello, world!\n";
|
||||||
|
Reference in New Issue
Block a user