Skip to content

Commit 567f976

Browse files
committed
C++11 features to implement server stuff.
1 parent 10244c6 commit 567f976

File tree

4 files changed

+53
-37
lines changed

4 files changed

+53
-37
lines changed

boost/network/message/wrappers/headers.hpp

-8
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,6 @@ namespace boost { namespace network {
1313

1414
struct message_base;
1515

16-
/** headers wrapper for messages.
17-
*
18-
* This exposes an interface similar to a map, indexable
19-
* using operator[] taking a string as the index and returns
20-
* a range of iterators (std::pair<iterator, iterator>)
21-
* whose keys are all equal to the index string.
22-
*
23-
*/
2416
struct headers_wrapper {
2517
typedef std::multimap<std::string, std::string> container_type;
2618
explicit headers_wrapper(message_base const & message);

boost/network/protocol/http/algorithms/flatten.hpp

-25
This file was deleted.

boost/network/protocol/http/server/connection/sync.hpp

+51-4
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
#define BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE 4096uL
1313
#endif
1414

15+
#include <utility>
16+
#include <iterator>
1517
#include <boost/enable_shared_from_this.hpp>
18+
#include <boost/network/constants.hpp>
1619
#include <boost/network/protocol/http/server/request_parser.hpp>
1720
#include <boost/network/protocol/http/request.hpp>
1821
#include <boost/network/protocol/http/response.hpp>
@@ -26,7 +29,6 @@
2629
#include <boost/lexical_cast.hpp>
2730
#include <boost/algorithm/string/case_conv.hpp>
2831
#include <boost/bind.hpp>
29-
#include <boost/network/protocol/http/algorithms/flatten.hpp>
3032

3133
namespace boost { namespace network { namespace http {
3234

@@ -187,8 +189,13 @@ class sync_server_connection : public boost::enable_shared_from_this<sync_server
187189
} else {
188190
response response_;
189191
handler_(request_, response_);
190-
std::vector<asio::const_buffer> response_buffers;
191-
flatten(response_, response_buffers);
192+
flatten_response();
193+
std::vector<asio::const_buffer> response_buffers(output_buffers_.size());
194+
std::transform(output_buffers_.begin(), output_buffers_.end(),
195+
response_buffers.begin(),
196+
[](buffer_type const &buffer) {
197+
return asio::const_buffer(buffer.data(), buffer.size());
198+
});
192199
boost::asio::async_write(
193200
socket_,
194201
response_buffers,
@@ -217,13 +224,15 @@ class sync_server_connection : public boost::enable_shared_from_this<sync_server
217224
}
218225

219226
void handle_write(system::error_code const &ec) {
227+
// First thing we do is clear out the output buffers.
228+
output_buffers_.clear();
220229
if (ec) {
221230
// TODO maybe log the error here.
222231
}
223232
}
224233

225234
void client_error() {
226-
static char const * bad_request =
235+
static char const bad_request[] =
227236
"HTTP/1.0 400 Bad Request\r\nConnection: close\r\nContent-Type: text/plain\r\nContent-Length: 12\r\n\r\nBad Request.";
228237

229238
asio::async_write(
@@ -262,6 +271,43 @@ class sync_server_connection : public boost::enable_shared_from_this<sync_server
262271
);
263272
}
264273

274+
void flatten_response() {
275+
uint16_t status = http::status(response_);
276+
std::string status_message = http::status_message(response_);
277+
headers_wrapper::container_type headers = network::headers(response_);
278+
std::ostringstream status_line;
279+
status_line << status << constants::space() << status_message << constants::space()
280+
<< constants::http_slash()
281+
<< "1.1" // TODO: make this a constant
282+
<< constants::crlf();
283+
segmented_write(status_line.str());
284+
std::ostringstream header_stream;
285+
for (decltype(headers)::value_type const &header : headers) {
286+
header_stream << header.first << constants::colon() << constants::space()
287+
<< header.second << constants::crlf();
288+
}
289+
header_stream << constants::crlf();
290+
segmented_write(header_stream.str());
291+
bool done = false;
292+
while (!done) {
293+
buffer_type buffer;
294+
response_.get_body([&done, &buffer](iterator_range<char const *> data) {
295+
if (boost::empty(data)) done = true;
296+
else std::copy(begin(data), end(data), buffer.begin());
297+
}, buffer.size());
298+
if (!done) output_buffers_.emplace_back(std::move(buffer));
299+
}
300+
}
301+
302+
void segmented_write(std::string data) {
303+
while (!boost::empty(data)) {
304+
buffer_type buffer;
305+
auto end = std::copy_n(boost::begin(data), buffer.size(), buffer.begin());
306+
data.erase(0, std::distance(buffer.begin(), end));
307+
output_buffers_.emplace_back(std::move(buffer));
308+
}
309+
}
310+
265311
boost::asio::io_service & service_;
266312
function<void(request const &, response &)> handler_;
267313
boost::asio::ip::tcp::socket socket_;
@@ -273,6 +319,7 @@ class sync_server_connection : public boost::enable_shared_from_this<sync_server
273319
request_parser parser_;
274320
request request_;
275321
response response_;
322+
std::list<buffer_type> output_buffers_;
276323
std::string partial_parsed;
277324
optional<system::system_error> error_encountered;
278325
bool read_body_;

libs/network/test/http/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,10 @@ if (Boost_FOUND)
8787
target_link_libraries(cpp-netlib-http-${test}
8888
${Boost_LIBRARIES}
8989
${CMAKE_THREAD_LIBS_INIT}
90+
cppnetlib-constants
9091
cppnetlib-uri
9192
cppnetlib-message
93+
cppnetlib-message-wrappers
9294
cppnetlib-http-message
9395
cppnetlib-http-servers
9496
cppnetlib-http-server-parsers

0 commit comments

Comments
 (0)