mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
Distinguish HTTP/1 messages from general HTTP messages:
The version field is moved into message_v1, all public interfaces are reworked to identify HTTP/1 wire format operations (suffix "_v1") versus general HTTP.
This commit is contained in:
@@ -5,15 +5,15 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_PARSER_IPP
|
||||
#ifndef BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||
#define BEAST_HTTP_IMPL_BASIC_PARSER_V1_IPP
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<bool isRequest, class Derived>
|
||||
bool
|
||||
basic_parser<isRequest, Derived>::
|
||||
basic_parser_v1<isRequest, Derived>::
|
||||
keep_alive() const
|
||||
{
|
||||
if(http_major_ > 0 && http_minor_ > 0)
|
||||
@@ -34,7 +34,7 @@ keep_alive() const
|
||||
template<bool isRequest, class Derived>
|
||||
template<class ConstBufferSequence, class>
|
||||
std::size_t
|
||||
basic_parser<isRequest, Derived>::
|
||||
basic_parser_v1<isRequest, Derived>::
|
||||
write(ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
static_assert(is_ConstBufferSequence<ConstBufferSequence>::value,
|
||||
@@ -51,7 +51,7 @@ write(ConstBufferSequence const& buffers, error_code& ec)
|
||||
|
||||
template<bool isRequest, class Derived>
|
||||
std::size_t
|
||||
basic_parser<isRequest, Derived>::
|
||||
basic_parser_v1<isRequest, Derived>::
|
||||
write(boost::asio::const_buffer const& buffer, error_code& ec)
|
||||
{
|
||||
using beast::http::detail::is_digit;
|
||||
@@ -1022,7 +1022,7 @@ write(boost::asio::const_buffer const& buffer, error_code& ec)
|
||||
|
||||
template<bool isRequest, class Derived>
|
||||
void
|
||||
basic_parser<isRequest, Derived>::
|
||||
basic_parser_v1<isRequest, Derived>::
|
||||
write_eof(error_code& ec)
|
||||
{
|
||||
switch(s_)
|
||||
@@ -1042,7 +1042,7 @@ write_eof(error_code& ec)
|
||||
|
||||
template<bool isRequest, class Derived>
|
||||
bool
|
||||
basic_parser<isRequest, Derived>::
|
||||
basic_parser_v1<isRequest, Derived>::
|
||||
needs_eof(std::true_type) const
|
||||
{
|
||||
return false;
|
||||
@@ -1050,7 +1050,7 @@ needs_eof(std::true_type) const
|
||||
|
||||
template<bool isRequest, class Derived>
|
||||
bool
|
||||
basic_parser<isRequest, Derived>::
|
||||
basic_parser_v1<isRequest, Derived>::
|
||||
needs_eof(std::false_type) const
|
||||
{
|
||||
// See RFC 2616 section 4.4
|
||||
@@ -5,33 +5,21 @@
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
|
||||
#ifndef BEAST_HTTP_IMPL_MESSAGE_IPP
|
||||
#define BEAST_HTTP_IMPL_MESSAGE_IPP
|
||||
#ifndef BEAST_HTTP_IMPL_MESSAGE_V1_IPP
|
||||
#define BEAST_HTTP_IMPL_MESSAGE_V1_IPP
|
||||
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <beast/http/rfc2616.hpp>
|
||||
#include <beast/write_streambuf.hpp>
|
||||
#include <beast/http/detail/has_content_length.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/http/detail/write_preparation.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace beast {
|
||||
namespace http {
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
message<isRequest, Body, Headers>::
|
||||
message()
|
||||
{
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
message<isRequest, Body, Headers>::
|
||||
message(request_params params)
|
||||
message_v1<isRequest, Body, Headers>::
|
||||
message_v1(request_params params)
|
||||
{
|
||||
static_assert(isRequest, "message is not a request");
|
||||
this->method = params.method;
|
||||
@@ -40,8 +28,8 @@ message(request_params params)
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
message<isRequest, Body, Headers>::
|
||||
message(response_params params)
|
||||
message_v1<isRequest, Body, Headers>::
|
||||
message_v1(response_params params)
|
||||
{
|
||||
static_assert(! isRequest, "message is not a response");
|
||||
this->status = params.status;
|
||||
@@ -49,126 +37,11 @@ message(response_params params)
|
||||
version = params.version;
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<class Streambuf>
|
||||
void
|
||||
message<isRequest, Body, Headers>::
|
||||
write_firstline(Streambuf& streambuf,
|
||||
std::true_type) const
|
||||
{
|
||||
write(streambuf, this->method);
|
||||
write(streambuf, " ");
|
||||
write(streambuf, this->url);
|
||||
switch(version)
|
||||
{
|
||||
case 10:
|
||||
write(streambuf, " HTTP/1.0\r\n");
|
||||
break;
|
||||
case 11:
|
||||
write(streambuf, " HTTP/1.1\r\n");
|
||||
break;
|
||||
default:
|
||||
write(streambuf, " HTTP/");
|
||||
write(streambuf, version / 10);
|
||||
write(streambuf, ".");
|
||||
write(streambuf, version % 10);
|
||||
write(streambuf, "\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
template<class Streambuf>
|
||||
void
|
||||
message<isRequest, Body, Headers>::
|
||||
write_firstline(Streambuf& streambuf,
|
||||
std::false_type) const
|
||||
{
|
||||
switch(version)
|
||||
{
|
||||
case 10:
|
||||
write(streambuf, "HTTP/1.0 ");
|
||||
break;
|
||||
case 11:
|
||||
write(streambuf, "HTTP/1.1 ");
|
||||
break;
|
||||
default:
|
||||
write(streambuf, " HTTP/");
|
||||
write(streambuf, version / 10);
|
||||
write(streambuf, ".");
|
||||
write(streambuf, version % 10);
|
||||
write(streambuf, " ");
|
||||
break;
|
||||
}
|
||||
write(streambuf, this->status);
|
||||
write(streambuf, " ");
|
||||
write(streambuf, this->reason);
|
||||
write(streambuf, "\r\n");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
set_connection(bool keep_alive,
|
||||
message<isRequest, Body, Headers>& req)
|
||||
{
|
||||
if(req.version >= 11)
|
||||
{
|
||||
if(! keep_alive)
|
||||
req.headers.replace("Connection", "close");
|
||||
else
|
||||
req.headers.erase("Connection");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(keep_alive)
|
||||
req.headers.replace("Connection", "keep-alive");
|
||||
else
|
||||
req.headers.erase("Connection");
|
||||
}
|
||||
}
|
||||
|
||||
template<class Body, class Headers,
|
||||
class OtherBody, class OtherAllocator>
|
||||
void
|
||||
set_connection(bool keep_alive,
|
||||
message<false, Body, Headers>& resp,
|
||||
message<true, OtherBody, OtherAllocator> const& req)
|
||||
{
|
||||
if(req.version >= 11)
|
||||
{
|
||||
if(rfc2616::token_in_list(req["Connection"], "close"))
|
||||
keep_alive = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(! rfc2616::token_in_list(req["Connection"], "keep-alive"))
|
||||
keep_alive = false;
|
||||
}
|
||||
set_connection(keep_alive, resp);
|
||||
}
|
||||
|
||||
template<class Streambuf, class FieldSequence>
|
||||
void
|
||||
write_fields(Streambuf& streambuf, FieldSequence const& fields)
|
||||
{
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
//static_assert(is_FieldSequence<FieldSequence>::value,
|
||||
// "FieldSequence requirements not met");
|
||||
for(auto const& field : fields)
|
||||
{
|
||||
write(streambuf, field.name());
|
||||
write(streambuf, ": ");
|
||||
write(streambuf, field.value());
|
||||
write(streambuf, "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
bool
|
||||
is_keep_alive(message<isRequest, Body, Headers> const& msg)
|
||||
is_keep_alive(message_v1<isRequest, Body, Headers> const& msg)
|
||||
{
|
||||
if(msg.version >= 11)
|
||||
{
|
||||
@@ -185,7 +58,7 @@ is_keep_alive(message<isRequest, Body, Headers> const& msg)
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
bool
|
||||
is_upgrade(message<isRequest, Body, Headers> const& msg)
|
||||
is_upgrade(message_v1<isRequest, Body, Headers> const& msg)
|
||||
{
|
||||
if(msg.version < 11)
|
||||
return false;
|
||||
@@ -207,14 +80,14 @@ template<bool isRequest, class Body, class Headers>
|
||||
inline
|
||||
void
|
||||
prepare_options(prepare_info& pi,
|
||||
message<isRequest, Body, Headers>& msg)
|
||||
message_v1<isRequest, Body, Headers>& msg)
|
||||
{
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
prepare_option(prepare_info& pi,
|
||||
message<isRequest, Body, Headers>& msg,
|
||||
message_v1<isRequest, Body, Headers>& msg,
|
||||
connection value)
|
||||
{
|
||||
pi.connection_value = value;
|
||||
@@ -225,7 +98,7 @@ template<
|
||||
class Opt, class... Opts>
|
||||
void
|
||||
prepare_options(prepare_info& pi,
|
||||
message<isRequest, Body, Headers>& msg,
|
||||
message_v1<isRequest, Body, Headers>& msg,
|
||||
Opt&& opt, Opts&&... opts)
|
||||
{
|
||||
prepare_option(pi, msg, opt);
|
||||
@@ -236,7 +109,7 @@ prepare_options(prepare_info& pi,
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
prepare_content_length(prepare_info& pi,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message_v1<isRequest, Body, Headers> const& msg,
|
||||
std::true_type)
|
||||
{
|
||||
typename Body::writer w(msg);
|
||||
@@ -247,7 +120,7 @@ prepare_content_length(prepare_info& pi,
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
prepare_content_length(prepare_info& pi,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message_v1<isRequest, Body, Headers> const& msg,
|
||||
std::false_type)
|
||||
{
|
||||
pi.content_length = boost::none;
|
||||
@@ -258,7 +131,7 @@ prepare_content_length(prepare_info& pi,
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
void
|
||||
prepare_connection(
|
||||
message<isRequest, Body, Headers>& msg)
|
||||
message_v1<isRequest, Body, Headers>& msg)
|
||||
{
|
||||
if(msg.version >= 11)
|
||||
{
|
||||
@@ -286,7 +159,7 @@ template<
|
||||
bool isRequest, class Body, class Headers,
|
||||
class... Options>
|
||||
void
|
||||
prepare(message<isRequest, Body, Headers>& msg,
|
||||
prepare(message_v1<isRequest, Body, Headers>& msg,
|
||||
Options&&... options)
|
||||
{
|
||||
// VFALCO TODO
|
||||
@@ -8,6 +8,7 @@
|
||||
#ifndef BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||
#define BEAST_HTTP_IMPL_READ_IPP_HPP
|
||||
|
||||
#include <beast/http/parser_v1.hpp>
|
||||
#include <beast/bind_handler.hpp>
|
||||
#include <beast/handler_alloc.hpp>
|
||||
#include <cassert>
|
||||
@@ -26,10 +27,10 @@ class read_op
|
||||
handler_alloc<char, Handler>;
|
||||
|
||||
using parser_type =
|
||||
parser<isRequest, Body, Headers>;
|
||||
parser_v1<isRequest, Body, Headers>;
|
||||
|
||||
using message_type =
|
||||
message<isRequest, Body, Headers>;
|
||||
message_v1<isRequest, Body, Headers>;
|
||||
|
||||
struct data
|
||||
{
|
||||
@@ -214,14 +215,14 @@ template<class SyncReadStream, class Streambuf,
|
||||
bool isRequest, class Body, class Headers>
|
||||
void
|
||||
read(SyncReadStream& stream, Streambuf& streambuf,
|
||||
message<isRequest, Body, Headers>& m,
|
||||
message_v1<isRequest, Body, Headers>& m,
|
||||
error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncReadStream<SyncReadStream>::value,
|
||||
"SyncReadStream requirements not met");
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
parser<isRequest, Body, Headers> p;
|
||||
parser_v1<isRequest, Body, Headers> p;
|
||||
bool started = false;
|
||||
for(;;)
|
||||
{
|
||||
@@ -264,7 +265,7 @@ template<class AsyncReadStream, class Streambuf,
|
||||
typename async_completion<
|
||||
ReadHandler, void(error_code)>::result_type
|
||||
async_read(AsyncReadStream& stream, Streambuf& streambuf,
|
||||
message<isRequest, Body, Headers>& m,
|
||||
message_v1<isRequest, Body, Headers>& m,
|
||||
ReadHandler&& handler)
|
||||
{
|
||||
static_assert(is_AsyncReadStream<AsyncReadStream>::value,
|
||||
|
||||
@@ -10,12 +10,13 @@
|
||||
|
||||
#include <beast/http/resume_context.hpp>
|
||||
#include <beast/http/detail/chunk_encode.hpp>
|
||||
#include <beast/http/detail/write_preparation.hpp>
|
||||
#include <beast/http/detail/has_content_length.hpp>
|
||||
#include <beast/buffer_cat.hpp>
|
||||
#include <beast/bind_handler.hpp>
|
||||
#include <beast/handler_alloc.hpp>
|
||||
#include <beast/streambuf.hpp>
|
||||
#include <beast/type_check.hpp>
|
||||
#include <beast/write_streambuf.hpp>
|
||||
#include <boost/asio/write.hpp>
|
||||
#include <boost/logic/tribool.hpp>
|
||||
#include <condition_variable>
|
||||
@@ -29,6 +30,114 @@ namespace http {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class Streambuf, class Body, class Headers>
|
||||
void
|
||||
write_firstline(Streambuf& streambuf,
|
||||
message_v1<true, Body, Headers> const& msg)
|
||||
{
|
||||
write(streambuf, msg.method);
|
||||
write(streambuf, " ");
|
||||
write(streambuf, msg.url);
|
||||
switch(msg.version)
|
||||
{
|
||||
case 10:
|
||||
write(streambuf, " HTTP/1.0\r\n");
|
||||
break;
|
||||
case 11:
|
||||
write(streambuf, " HTTP/1.1\r\n");
|
||||
break;
|
||||
default:
|
||||
write(streambuf, " HTTP/");
|
||||
write(streambuf, msg.version / 10);
|
||||
write(streambuf, ".");
|
||||
write(streambuf, msg.version % 10);
|
||||
write(streambuf, "\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Streambuf, class Body, class Headers>
|
||||
void
|
||||
write_firstline(Streambuf& streambuf,
|
||||
message_v1<false, Body, Headers> const& msg)
|
||||
{
|
||||
switch(msg.version)
|
||||
{
|
||||
case 10:
|
||||
write(streambuf, "HTTP/1.0 ");
|
||||
break;
|
||||
case 11:
|
||||
write(streambuf, "HTTP/1.1 ");
|
||||
break;
|
||||
default:
|
||||
write(streambuf, " HTTP/");
|
||||
write(streambuf, msg.version / 10);
|
||||
write(streambuf, ".");
|
||||
write(streambuf, msg.version % 10);
|
||||
write(streambuf, " ");
|
||||
break;
|
||||
}
|
||||
write(streambuf, msg.status);
|
||||
write(streambuf, " ");
|
||||
write(streambuf, msg.reason);
|
||||
write(streambuf, "\r\n");
|
||||
}
|
||||
|
||||
template<class Streambuf, class FieldSequence>
|
||||
void
|
||||
write_fields(Streambuf& streambuf, FieldSequence const& fields)
|
||||
{
|
||||
static_assert(is_Streambuf<Streambuf>::value,
|
||||
"Streambuf requirements not met");
|
||||
//static_assert(is_FieldSequence<FieldSequence>::value,
|
||||
// "FieldSequence requirements not met");
|
||||
for(auto const& field : fields)
|
||||
{
|
||||
write(streambuf, field.name());
|
||||
write(streambuf, ": ");
|
||||
write(streambuf, field.value());
|
||||
write(streambuf, "\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
struct write_preparation
|
||||
{
|
||||
using headers_type =
|
||||
basic_headers<std::allocator<char>>;
|
||||
|
||||
message_v1<isRequest, Body, Headers> const& msg;
|
||||
typename Body::writer w;
|
||||
streambuf sb;
|
||||
bool chunked;
|
||||
bool close;
|
||||
|
||||
explicit
|
||||
write_preparation(
|
||||
message_v1<isRequest, Body, Headers> const& msg_)
|
||||
: msg(msg_)
|
||||
, w(msg)
|
||||
, chunked(rfc2616::token_in_list(
|
||||
msg.headers["Transfer-Encoding"], "chunked"))
|
||||
, close(rfc2616::token_in_list(
|
||||
msg.headers["Connection"], "close") ||
|
||||
(msg.version < 11 && ! msg.headers.exists(
|
||||
"Content-Length")))
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
init(error_code& ec)
|
||||
{
|
||||
w.init(ec);
|
||||
if(ec)
|
||||
return;
|
||||
write_firstline(sb, msg);
|
||||
write_fields(sb, msg.headers);
|
||||
beast::write(sb, "\r\n");
|
||||
}
|
||||
};
|
||||
|
||||
template<class Stream, class Handler,
|
||||
bool isRequest, class Body, class Headers>
|
||||
class write_op
|
||||
@@ -50,7 +159,7 @@ class write_op
|
||||
|
||||
template<class DeducedHandler>
|
||||
data(DeducedHandler&& h_, Stream& s_,
|
||||
message<isRequest, Body, Headers> const& m_)
|
||||
message_v1<isRequest, Body, Headers> const& m_)
|
||||
: s(s_)
|
||||
, wp(m_)
|
||||
, h(std::forward<DeducedHandler>(h_))
|
||||
@@ -356,7 +465,21 @@ template<class SyncWriteStream,
|
||||
bool isRequest, class Body, class Headers>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message_v1<isRequest, Body, Headers> const& msg)
|
||||
{
|
||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||
"SyncWriteStream requirements not met");
|
||||
error_code ec;
|
||||
write(stream, msg, ec);
|
||||
if(ec)
|
||||
throw boost::system::system_error{ec};
|
||||
}
|
||||
|
||||
template<class SyncWriteStream,
|
||||
bool isRequest, class Body, class Headers>
|
||||
void
|
||||
write(SyncWriteStream& stream,
|
||||
message_v1<isRequest, Body, Headers> const& msg,
|
||||
boost::system::error_code& ec)
|
||||
{
|
||||
static_assert(is_SyncWriteStream<SyncWriteStream>::value,
|
||||
@@ -441,7 +564,7 @@ template<class AsyncWriteStream,
|
||||
typename async_completion<
|
||||
WriteHandler, void(error_code)>::result_type
|
||||
async_write(AsyncWriteStream& stream,
|
||||
message<isRequest, Body, Headers> const& msg,
|
||||
message_v1<isRequest, Body, Headers> const& msg,
|
||||
WriteHandler&& handler)
|
||||
{
|
||||
static_assert(
|
||||
@@ -506,7 +629,7 @@ public:
|
||||
template<bool isRequest, class Body, class Headers>
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os,
|
||||
message<isRequest, Body, Headers> const& msg)
|
||||
message_v1<isRequest, Body, Headers> const& msg)
|
||||
{
|
||||
detail::ostream_SyncStream oss(os);
|
||||
error_code ec;
|
||||
|
||||
Reference in New Issue
Block a user