Example HTTP server fixes

This commit is contained in:
Vinnie Falco
2017-08-08 17:38:48 -07:00
parent 0175102151
commit d613feae01
14 changed files with 38 additions and 86 deletions

View File

@@ -2,6 +2,7 @@ Version 103:
* Boost test matrix fixes * Boost test matrix fixes
* Tidy up allocator usage * Tidy up allocator usage
* Example HTTP server fixes
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

View File

@@ -16,7 +16,6 @@ add_executable (advanced-server-flex
${PROJECT_SOURCE_DIR}/example/common/detect_ssl.hpp ${PROJECT_SOURCE_DIR}/example/common/detect_ssl.hpp
${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp ${PROJECT_SOURCE_DIR}/example/common/server_certificate.hpp
${PROJECT_SOURCE_DIR}/example/common/ssl_stream.hpp ${PROJECT_SOURCE_DIR}/example/common/ssl_stream.hpp
${PROJECT_SOURCE_DIR}/example/common/write_msg.hpp
Jamfile Jamfile
advanced_server_flex.cpp advanced_server_flex.cpp
) )

View File

@@ -196,7 +196,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),
@@ -564,7 +564,6 @@ class http_session
virtual void operator()() = 0; virtual void operator()() = 0;
}; };
bool busy_ = false; // true if a write is in progress
http_session& self_; http_session& self_;
std::vector<std::unique_ptr<work>> items_; std::vector<std::unique_ptr<work>> items_;
@@ -581,7 +580,7 @@ class http_session
bool bool
is_full() const is_full() const
{ {
return items_.size() + (busy_ ? 1 : 0) >= limit; return items_.size() >= limit;
} }
// Called when a message finishes sending // Called when a message finishes sending
@@ -589,18 +588,12 @@ class http_session
bool bool
on_write() on_write()
{ {
BOOST_ASSERT(busy_); BOOST_ASSERT(! items_.empty());
auto const do_read = items_.size() + (busy_ ? 1 : 0) >= limit; auto const was_full = is_full();
items_.erase(items_.begin());
if(! items_.empty()) if(! items_.empty())
{ (*items_.front())();
(*items_.back())(); return was_full;
items_.erase(items_.begin());
}
else
{
busy_ = false;
}
return do_read;
} }
// Called by the HTTP handler to send a response. // Called by the HTTP handler to send a response.
@@ -608,24 +601,6 @@ class http_session
void void
operator()(http::message<isRequest, Body, Fields>&& msg) operator()(http::message<isRequest, Body, Fields>&& msg)
{ {
// See if a write is in progress
if(! busy_)
{
// No write in progress so start one
busy_ = true;
// This function takes ownership of the message by moving
// it into a temporary buffer, otherwise we would have
// to manage the lifetime of the message and serializer.
return async_write_msg(
self_.derived().stream(),
std::move(msg),
self_.strand_.wrap(std::bind(
&http_session::on_write,
self_.derived().shared_from_this(),
std::placeholders::_1)));
}
// This holds a work item // This holds a work item
struct work_impl : work struct work_impl : work
{ {
@@ -643,9 +618,9 @@ class http_session
void void
operator()() operator()()
{ {
async_write_msg( http::async_write(
self_.derived().stream(), self_.derived().stream(),
std::move(msg_), msg_,
self_.strand_.wrap(std::bind( self_.strand_.wrap(std::bind(
&http_session::on_write, &http_session::on_write,
self_.derived().shared_from_this(), self_.derived().shared_from_this(),
@@ -653,9 +628,12 @@ class http_session
} }
}; };
// A write is in progress, so allocate storage to // Allocate and store the work
// save this work item so we can invoke it later.
items_.emplace_back(new work_impl(self_, std::move(msg))); items_.emplace_back(new work_impl(self_, std::move(msg)));
// If there was no previous work, start this one
if(items_.size() == 1)
(*items_.front())();
} }
}; };

View File

@@ -8,12 +8,10 @@
# #
GroupSources(include/boost/beast beast) GroupSources(include/boost/beast beast)
GroupSources(example/common common)
GroupSources(example/advanced/server "/") GroupSources(example/advanced/server "/")
add_executable (advanced-server add_executable (advanced-server
${BOOST_BEAST_INCLUDES} ${BOOST_BEAST_INCLUDES}
${PROJECT_SOURCE_DIR}/example/common/write_msg.hpp
Jamfile Jamfile
advanced_server.cpp advanced_server.cpp
) )

View File

@@ -13,8 +13,6 @@
// //
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
#include "example/common/write_msg.hpp"
#include <boost/beast/core.hpp> #include <boost/beast/core.hpp>
#include <boost/beast/http.hpp> #include <boost/beast/http.hpp>
#include <boost/beast/websocket.hpp> #include <boost/beast/websocket.hpp>
@@ -191,7 +189,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),
@@ -367,7 +365,6 @@ class http_session : public std::enable_shared_from_this<http_session>
virtual void operator()() = 0; virtual void operator()() = 0;
}; };
bool busy_ = false; // true if a write is in progress
http_session& self_; http_session& self_;
std::vector<std::unique_ptr<work>> items_; std::vector<std::unique_ptr<work>> items_;
@@ -384,7 +381,7 @@ class http_session : public std::enable_shared_from_this<http_session>
bool bool
is_full() const is_full() const
{ {
return items_.size() + (busy_ ? 1 : 0) >= limit; return items_.size() >= limit;
} }
// Called when a message finishes sending // Called when a message finishes sending
@@ -392,18 +389,12 @@ class http_session : public std::enable_shared_from_this<http_session>
bool bool
on_write() on_write()
{ {
BOOST_ASSERT(busy_); BOOST_ASSERT(! items_.empty());
auto const do_read = items_.size() + (busy_ ? 1 : 0) >= limit; auto const was_full = is_full();
items_.erase(items_.begin());
if(! items_.empty()) if(! items_.empty())
{ (*items_.front())();
(*items_.back())(); return was_full;
items_.erase(items_.begin());
}
else
{
busy_ = false;
}
return do_read;
} }
// Called by the HTTP handler to send a response. // Called by the HTTP handler to send a response.
@@ -411,24 +402,6 @@ class http_session : public std::enable_shared_from_this<http_session>
void void
operator()(http::message<isRequest, Body, Fields>&& msg) operator()(http::message<isRequest, Body, Fields>&& msg)
{ {
// See if a write is in progress
if(! busy_)
{
// No write in progress so start one
busy_ = true;
// This function takes ownership of the message by moving
// it into a temporary buffer, otherwise we would have
// to manage the lifetime of the message and serializer.
return async_write_msg(
self_.socket_,
std::move(msg),
self_.strand_.wrap(std::bind(
&http_session::on_write,
self_.shared_from_this(),
std::placeholders::_1)));
}
// This holds a work item // This holds a work item
struct work_impl : work struct work_impl : work
{ {
@@ -446,9 +419,9 @@ class http_session : public std::enable_shared_from_this<http_session>
void void
operator()() operator()()
{ {
async_write_msg( http::async_write(
self_.socket_, self_.socket_,
std::move(msg_), msg_,
self_.strand_.wrap(std::bind( self_.strand_.wrap(std::bind(
&http_session::on_write, &http_session::on_write,
self_.shared_from_this(), self_.shared_from_this(),
@@ -456,9 +429,12 @@ class http_session : public std::enable_shared_from_this<http_session>
} }
}; };
// A write is in progress, so allocate storage to // Allocate and store the work
// save this work item so we can invoke it later.
items_.emplace_back(new work_impl(self_, std::move(msg))); items_.emplace_back(new work_impl(self_, std::move(msg)));
// If there was no previous work, start this one
if(items_.size() == 1)
(*items_.front())();
} }
}; };

View File

@@ -191,7 +191,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),

View File

@@ -188,7 +188,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),

View File

@@ -189,7 +189,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),

View File

@@ -185,7 +185,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),

View File

@@ -191,7 +191,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),

View File

@@ -192,7 +192,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),

View File

@@ -189,7 +189,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),

View File

@@ -186,7 +186,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),

View File

@@ -184,7 +184,7 @@ handle_request(
return send(std::move(res)); return send(std::move(res));
} }
// Respond to HEAD request // Respond to GET request
http::response<http::file_body> res{ http::response<http::file_body> res{
std::piecewise_construct, std::piecewise_construct,
std::make_tuple(std::move(body)), std::make_tuple(std::move(body)),