12
12
#define BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE 4096uL
13
13
#endif
14
14
15
+ #include < utility>
16
+ #include < iterator>
15
17
#include < boost/enable_shared_from_this.hpp>
18
+ #include < boost/network/constants.hpp>
16
19
#include < boost/network/protocol/http/server/request_parser.hpp>
17
20
#include < boost/network/protocol/http/request.hpp>
18
21
#include < boost/network/protocol/http/response.hpp>
26
29
#include < boost/lexical_cast.hpp>
27
30
#include < boost/algorithm/string/case_conv.hpp>
28
31
#include < boost/bind.hpp>
29
- #include < boost/network/protocol/http/algorithms/flatten.hpp>
30
32
31
33
namespace boost { namespace network { namespace http {
32
34
@@ -187,8 +189,13 @@ class sync_server_connection : public boost::enable_shared_from_this<sync_server
187
189
} else {
188
190
response response_;
189
191
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
+ });
192
199
boost::asio::async_write (
193
200
socket_,
194
201
response_buffers,
@@ -217,13 +224,15 @@ class sync_server_connection : public boost::enable_shared_from_this<sync_server
217
224
}
218
225
219
226
void handle_write (system::error_code const &ec) {
227
+ // First thing we do is clear out the output buffers.
228
+ output_buffers_.clear ();
220
229
if (ec) {
221
230
// TODO maybe log the error here.
222
231
}
223
232
}
224
233
225
234
void client_error () {
226
- static char const * bad_request =
235
+ static char const bad_request[] =
227
236
" HTTP/1.0 400 Bad Request\r\n Connection: close\r\n Content-Type: text/plain\r\n Content-Length: 12\r\n\r\n Bad Request." ;
228
237
229
238
asio::async_write (
@@ -262,6 +271,43 @@ class sync_server_connection : public boost::enable_shared_from_this<sync_server
262
271
);
263
272
}
264
273
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
+
265
311
boost::asio::io_service & service_;
266
312
function<void (request const &, response &)> handler_;
267
313
boost::asio::ip::tcp::socket socket_;
@@ -273,6 +319,7 @@ class sync_server_connection : public boost::enable_shared_from_this<sync_server
273
319
request_parser parser_;
274
320
request request_;
275
321
response response_;
322
+ std::list<buffer_type> output_buffers_;
276
323
std::string partial_parsed;
277
324
optional<system::system_error> error_encountered;
278
325
bool read_body_;
0 commit comments