Skip to content

Commit 3049355

Browse files
committed
Implementing the Linearize Algorithm
This first part of the patch removes the linearization of the HTTP Request algorithm from the bowels of the connection_helper detail that exposes the linearize function to be used for all the client implementations. This refactoring is crucial to make the linerize algorithm a top-level algorithm that deals with requests, responses, and normal messages. This paves the way for a single point of extension for messages that have to be linearized to a buffer. Documentation and support for linearization of response objects will follow.
1 parent 159a22a commit 3049355

19 files changed

+237
-163
lines changed

boost/network/constants.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ namespace boost { namespace network {
2626
return dot_;
2727
}
2828

29+
static char dot_char() { return '.'; }
30+
2931
static char const * http_slash() {
3032
static char http_slash_[] = { 'H', 'T', 'T', 'P', '/', 0 };
3133
return http_slash_;
@@ -36,11 +38,15 @@ namespace boost { namespace network {
3638
return space_;
3739
}
3840

41+
static char space_char() { return ' '; }
42+
3943
static char const * slash() {
4044
static char slash_[] = {'/', 0};
4145
return slash_;
4246
}
4347

48+
static char slash_char() { return '/'; }
49+
4450
static char const * host() {
4551
static char host_[] = {'H', 'o', 's', 't', 0};
4652
return host_;
@@ -50,6 +56,8 @@ namespace boost { namespace network {
5056
static char colon_[] = {':', 0};
5157
return colon_;
5258
}
59+
60+
static char colon_char() { return ':'; }
5361

5462
static char const * accept() {
5563
static char accept_[] = {'A', 'c', 'c', 'e', 'p', 't', 0};
@@ -91,6 +99,28 @@ namespace boost { namespace network {
9199
return cpp_netlib_slash_;
92100
}
93101

102+
static char question_mark_char() {
103+
return '?';
104+
}
105+
106+
static char hash_char() {
107+
return '#';
108+
}
109+
110+
static char const * connection() {
111+
static char connection_[] = {
112+
'C','o','n','n','e','c','t','i','o','n',0
113+
};
114+
return connection_;
115+
}
116+
117+
static char const * close() {
118+
static char close_[] = {
119+
'C','l','o','s','e', 0
120+
};
121+
return close_;
122+
}
123+
94124
};
95125

96126
template <class Tag>

boost/network/message/wrappers/body.hpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@
99

1010
#include <boost/network/traits/string.hpp>
1111
#include <boost/network/detail/wrapper_base.hpp>
12+
#include <boost/range/iterator.hpp>
1213

1314
namespace boost { namespace network {
1415

16+
template <class Message>
17+
struct body_range {
18+
typedef typename boost::iterator_range<typename Message::string_type::const_iterator> type;
19+
};
20+
1521
namespace impl {
1622
template <class Tag>
1723
struct body_wrapper : public detail::wrapper_base<Tag, basic_message<Tag> > {
@@ -30,6 +36,23 @@ namespace boost { namespace network {
3036
std::size_t size() const {
3137
return wrapper_base::_message.body().size();
3238
}
39+
40+
operator boost::iterator_range<
41+
typename boost::range_iterator<string_type>::type
42+
> () const {
43+
return boost::make_iterator_range(wrapper_base::_message.body());
44+
}
45+
46+
typename string_type::const_iterator
47+
begin() const {
48+
return wrapper_base::_message.body().begin();
49+
}
50+
51+
typename string_type::const_iterator
52+
end() const {
53+
return wrapper_base::_message.body().end();
54+
}
55+
3356
};
3457

3558
template <class Tag>
@@ -49,6 +72,10 @@ namespace boost { namespace network {
4972
std::size_t size() const {
5073
return wrapper_base::_message.body().size();
5174
}
75+
76+
operator boost::range_iterator<string_type> () const {
77+
return boost::make_iterator_range(wrapper_base::_message.body());
78+
}
5279
};
5380

5481
} // namespace impl

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

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@
1111
#include <boost/network/protocol/http/message/header_concept.hpp>
1212
#include <boost/network/constants.hpp>
1313
#include <boost/concept_check.hpp>
14+
#include <boost/range/algorithm/copy.hpp>
1415

1516
namespace boost { namespace network { namespace http {
1617

1718
template <class Tag>
18-
struct linearize {
19+
struct linearize_header {
1920
typedef typename string<Tag>::type string_type;
2021

2122
template <class Arguments>
@@ -40,11 +41,97 @@ namespace boost { namespace network { namespace http {
4041
return header_line.str();
4142
}
4243
};
44+
45+
template <class Tag, class OutputIterator>
46+
OutputIterator linearize(
47+
basic_request<Tag> const & request,
48+
typename string<Tag>::type const & method,
49+
unsigned version_major,
50+
unsigned version_minor,
51+
OutputIterator oi
52+
)
53+
{
54+
typedef constants<Tag> consts;
55+
typedef typename string<Tag>::type string_type;
56+
static string_type
57+
http_slash = consts::http_slash()
58+
, accept = consts::accept()
59+
, accept_mime = consts::default_accept_mime()
60+
, accept_encoding = consts::accept_encoding()
61+
, default_accept_encoding = consts::default_accept_encoding()
62+
, crlf = consts::crlf()
63+
, host = consts::host()
64+
, connection = consts::connection()
65+
, close = consts::close()
66+
;
67+
boost::copy(method, oi);
68+
*oi = consts::space_char();
69+
if (request.path().empty() || request.path()[0] != consts::slash_char())
70+
*oi = consts::slash_char();
71+
boost::copy(request.path(), oi);
72+
if (!request.query().empty()) {
73+
*oi = consts::question_mark_char();
74+
boost::copy(request.query(), oi);
75+
}
76+
if (!request.anchor().empty()) {
77+
*oi = consts::hash_char();
78+
boost::copy(request.anchor(), oi);
79+
}
80+
*oi = consts::space_char();
81+
boost::copy(http_slash, oi);
82+
string_type version_major_str = boost::lexical_cast<string_type>(version_major),
83+
version_minor_str = boost::lexical_cast<string_type>(version_minor);
84+
boost::copy(version_major_str, oi);
85+
*oi = consts::dot_char();
86+
boost::copy(version_minor_str, oi);
87+
boost::copy(crlf, oi);
88+
boost::copy(host, oi);
89+
*oi = consts::colon_char();
90+
*oi = consts::space_char();
91+
boost::copy(request.host(), oi);
92+
boost::copy(host, oi);
93+
boost::copy(accept, oi);
94+
*oi = consts::colon_char();
95+
*oi = consts::space_char();
96+
boost::copy(accept_mime, oi);
97+
boost::copy(crlf, oi);
98+
if (version_major == 1u && version_minor == 1u) {
99+
boost::copy(accept_encoding, oi);
100+
*oi = consts::colon_char();
101+
*oi = consts::space_char();
102+
boost::copy(default_accept_encoding, oi);
103+
}
104+
typedef typename headers_range<basic_request<Tag> >::type headers_range;
105+
typedef typename range_iterator<headers_range>::type headers_iterator;
106+
headers_range request_headers = headers(request);
107+
headers_iterator iterator = boost::begin(request_headers),
108+
end = boost::end(request_headers);
109+
for (; iterator != end; ++iterator) {
110+
string_type header_name = name(*iterator),
111+
header_value = value(*iterator);
112+
boost::copy(header_name, oi);
113+
*oi = consts::colon_char();
114+
*oi = consts::space_char();
115+
boost::copy(header_value, oi);
116+
boost::copy(crlf, oi);
117+
}
118+
if (!connection_keepalive<Tag>::value) {
119+
boost::copy(connection, oi);
120+
*oi = consts::colon_char();
121+
*oi = consts::space_char();
122+
boost::copy(close, oi);
123+
boost::copy(crlf, oi);
124+
}
125+
boost::copy(crlf, oi);
126+
typename body_range<basic_request<Tag> >::type body_data = body(request).range();
127+
return boost::copy(body_data, oi);
128+
}
43129

44-
} /* linearize */
130+
} /* http */
45131

46132
} /* net */
47133

48134
} /* boost */
49135

50136
#endif /* BOOST_NETWORK_PROTOCOL_HTTP_ALGORITHMS_LINEARIZE_HPP_20101028 */
137+

boost/network/protocol/http/detail/connection_helper.hpp

Lines changed: 0 additions & 88 deletions
This file was deleted.

boost/network/protocol/http/impl/http_sync_connection.hpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
// (See accompanying file LICENSE_1_0.txt or copy at
88
// http://www.boost.org/LICENSE_1_0.txt)
99

10+
#include <boost/network/protocol/http/algorithms/linearize.hpp>
11+
#include <iterator>
12+
1013
namespace boost { namespace network { namespace http { namespace impl {
1114

1215
template <class Tag, unsigned version_major, unsigned version_minor>
@@ -16,7 +19,7 @@ namespace boost { namespace network { namespace http { namespace impl {
1619
struct sync_connection_base;
1720

1821
template <class Tag, unsigned version_major, unsigned version_minor>
19-
struct http_sync_connection : public virtual sync_connection_base<Tag, version_major, version_minor>, detail::connection_helper<Tag, version_major, version_minor>, sync_connection_base_impl<Tag, version_major, version_minor> {
22+
struct http_sync_connection : public virtual sync_connection_base<Tag, version_major, version_minor>, sync_connection_base_impl<Tag, version_major, version_minor> {
2023
typedef typename resolver_policy<Tag>::type resolver_base;
2124
typedef typename resolver_base::resolver_type resolver_type;
2225
typedef typename string<Tag>::type string_type;
@@ -32,7 +35,8 @@ namespace boost { namespace network { namespace http { namespace impl {
3235

3336
void send_request_impl(string_type const & method, basic_request<Tag> const & request_) {
3437
boost::asio::streambuf request_buffer;
35-
this->create_request(request_buffer, method, request_);
38+
linearize(request_, method, version_major, version_minor,
39+
std::ostreambuf_iterator<typename char_<Tag>::type>(&request_buffer));
3640
connection_base::send_request_impl(socket_, method, request_buffer);
3741
}
3842

boost/network/protocol/http/impl/https_sync_connection.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace boost { namespace network { namespace http { namespace impl {
1818
struct sync_connection_base;
1919

2020
template <class Tag, unsigned version_major, unsigned version_minor>
21-
struct https_sync_connection : public virtual sync_connection_base<Tag,version_major,version_minor>, detail::connection_helper<Tag, version_major, version_minor>, sync_connection_base_impl<Tag, version_major, version_minor> {
21+
struct https_sync_connection : public virtual sync_connection_base<Tag,version_major,version_minor>, sync_connection_base_impl<Tag, version_major, version_minor> {
2222
typedef typename resolver_policy<Tag>::type resolver_base;
2323
typedef typename resolver_base::resolver_type resolver_type;
2424
typedef typename string<Tag>::type string_type;
@@ -42,7 +42,8 @@ namespace boost { namespace network { namespace http { namespace impl {
4242

4343
void send_request_impl(string_type const & method, basic_request<Tag> const & request_) {
4444
boost::asio::streambuf request_buffer;
45-
this->create_request(request_buffer, method, request_);
45+
linearize(request_, method, version_major, version_minor,
46+
std::ostreambuf_iterator<typename char_<Tag>::type>(&request_buffer));
4647
connection_base::send_request_impl(socket_, method, request_buffer);
4748
}
4849

boost/network/protocol/http/impl/sync_connection_base.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
// http://www.boost.org/LICENSE_1_0.txt)
88

99
#include <boost/network/protocol/http/traits/resolver_policy.hpp>
10-
#include <boost/network/protocol/http/detail/connection_helper.hpp>
1110
#include <boost/network/traits/ostringstream.hpp>
1211
#include <boost/network/traits/istringstream.hpp>
1312
#include <boost/asio/streambuf.hpp>

boost/network/protocol/http/message/header/name.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ namespace boost { namespace network { namespace http {
1818

1919
template <class T1, class T2>
2020
T1 &
21-
name(std::pair<T1,T2> & p) {
21+
name(std::pair<T1,T2> const & p) {
2222
return p.first;
2323
}
2424

2525
template <class Tag>
26-
typename string<Tag>::type &
27-
name(response_header<Tag> & h) {
26+
typename string<Tag>::type const &
27+
name(response_header<Tag> const & h) {
2828
return h.name;
2929
}
3030

3131
template <class Tag>
32-
typename string<Tag>::type &
33-
name(request_header<Tag> & h) {
32+
typename string<Tag>::type const &
33+
name(request_header<Tag> const & h) {
3434
return h.name;
3535
}
3636

0 commit comments

Comments
 (0)