1
1
2
- // Copyright Dean Michael Berris 2007-2008 .
2
+ // Copyright Dean Michael Berris 2007-2009 .
3
3
// Distributed under the Boost Software License, Version 1.0.
4
4
// (See accompanying file LICENSE_1_0.txt or copy at
5
5
// http://www.boost.org/LICENSE_1_0.txt)
8
8
#define __NETWORK_PROTOCOL_HTTP_CLIENT_20070908_1_HPP__
9
9
10
10
#ifndef BOOST_NETLIB_VERSION
11
- #define BOOST_NETLIB_VERSION " 0.3 "
11
+ #define BOOST_NETLIB_VERSION " 0.5 "
12
12
#endif
13
13
14
14
#include < boost/network/traits/ostringstream.hpp>
15
15
#include < boost/network/protocol/http/message.hpp>
16
16
#include < boost/network/protocol/http/response.hpp>
17
17
#include < boost/network/protocol/http/request.hpp>
18
+ #include < boost/network/protocol/http/traits/resolver_policy.hpp>
18
19
#include < boost/asio.hpp>
19
20
#include < boost/lexical_cast.hpp>
20
21
#include < boost/algorithm/string/classification.hpp>
29
30
30
31
namespace boost {namespace network {namespace http {
31
32
32
- template <class tag ,unsigned version_major,unsigned version_minor>
33
- class basic_client {
33
+ template <class Tag ,unsigned version_major,unsigned version_minor>
34
+ class basic_client : resolver_policy<Tag>::type {
34
35
35
36
private:
37
+ typedef typename resolver_policy<Tag>::type resolver_base;
36
38
boost::asio::io_service service_;
37
- boost::asio::ip::tcp::resolver resolver_;
38
- bool cache_resolved_;
39
+ typename resolver_base::resolver_type resolver_;
39
40
bool follow_redirect_;
40
41
41
- typedef std::pair<
42
- boost::asio::ip::tcp::resolver::iterator,
43
- boost::asio::ip::tcp::resolver::iterator
44
- > resolver_iterator_pair;
45
-
46
- typedef typename string<tag>::type string_type;
47
-
48
- typedef std::map<string_type, resolver_iterator_pair> resolved_cache;
49
- resolved_cache endpoint_cache_;
50
-
51
- resolver_iterator_pairresolve (string_typeconst & hostname, string_typeconst & port) {
52
- if (cache_resolved_) {
53
- typename resolved_cache::iterator cached_iterator =
54
- endpoint_cache_.find (hostname);
55
- if (cached_iterator == endpoint_cache_.end ()) {
56
- bool inserted =false ;
57
- boost::tie (cached_iterator, inserted) =
58
- endpoint_cache_.insert (
59
- std::make_pair (
60
- hostname,
61
- std::make_pair (
62
- resolver_.resolve (
63
- boost::asio::ip::tcp::resolver::query (
64
- hostname,
65
- port,
66
- boost::asio::ip::tcp::resolver_query::numeric_service
67
- )
68
- )
69
- ,boost::asio::ip::tcp::resolver::iterator ()
70
- )
71
- )
72
- );
73
- };
74
- return cached_iterator->second ;
75
- };
76
-
77
- return std::make_pair (
78
- resolver_.resolve (
79
- boost::asio::ip::tcp::resolver::query (
80
- hostname,
81
- port,
82
- boost::asio::ip::tcp::resolver_query::numeric_service
83
- )
84
- )
85
- ,
86
- boost::asio::ip::tcp::resolver::iterator ()
87
- );
88
- };
42
+ typedef typename string<Tag>::type string_type;
89
43
90
44
void init_socket (boost::asio::ip::tcp::socket & socket_, string_typeconst & hostname, string_typeconst & port) {
91
45
using boost::asio::ip::tcp;
92
46
93
47
boost::system::error_code error = boost::asio::error::host_not_found;
94
48
95
49
tcp::resolver::iterator endpoint_iterator, end;
96
- boost::tie (endpoint_iterator, end) =resolve (hostname, port);
50
+ boost::tie (endpoint_iterator, end) =resolve (resolver_, hostname, port);
97
51
98
52
while (error && endpoint_iterator != end) {
99
53
socket_.close ();
@@ -104,7 +58,7 @@ namespace boost { namespace network { namespace http {
104
58
throw boost::system::system_error (error);
105
59
};
106
60
107
- void create_request (boost::asio::streambuf & request_buffer, string_typeconst & method, basic_request<tag > request_)const {
61
+ void create_request (boost::asio::streambuf & request_buffer, string_typeconst & method, basic_request<Tag > request_)const {
108
62
std::ostreamrequest_stream (&request_buffer);
109
63
110
64
request_stream
@@ -139,8 +93,7 @@ namespace boost { namespace network { namespace http {
139
93
};
140
94
141
95
range =headers (request_)[" user-agent" ];
142
- if (begin (range) ==end (range))
143
- request_stream <<" User-Agent: cpp-netlib/" << BOOST_NETLIB_VERSION <<" \r\n " ;
96
+ if (begin (range) ==end (range)) request_stream <<" User-Agent: cpp-netlib/" << BOOST_NETLIB_VERSION <<" \r\n " ;
144
97
145
98
request_stream
146
99
<<" Connection: close\r\n\r\n " ;
@@ -150,13 +103,13 @@ namespace boost { namespace network { namespace http {
150
103
request_stream << body_;
151
104
};
152
105
153
- void send_request (boost::asio::ip::tcp::socket & socket, string_typeconst & method, basic_request<tag >const & request_)const {
106
+ void send_request (boost::asio::ip::tcp::socket & socket, string_typeconst & method, basic_request<Tag >const & request_)const {
154
107
boost::asio::streambuf request_buffer;
155
108
create_request (request_buffer, method, request_);
156
109
write (socket, request_buffer);
157
110
};
158
111
159
- void read_status (basic_response<tag > & response_, boost::asio::ip::tcp::socket & socket, boost::asio::streambuf & response_buffer)const {
112
+ void read_status (basic_response<Tag > & response_, boost::asio::ip::tcp::socket & socket, boost::asio::streambuf & response_buffer)const {
160
113
boost::asio::read_until (socket, response_buffer," \r\n " );
161
114
std::istreamresponse_stream (&response_buffer);
162
115
string_type http_version;
@@ -176,7 +129,7 @@ namespace boost { namespace network { namespace http {
176
129
response_.status_message () = status_message;
177
130
};
178
131
179
- void read_headers (basic_response<tag > & response_, boost::asio::ip::tcp::socket & socket, boost::asio::streambuf & response_buffer)const {
132
+ void read_headers (basic_response<Tag > & response_, boost::asio::ip::tcp::socket & socket, boost::asio::streambuf & response_buffer)const {
180
133
boost::asio::read_until (socket, response_buffer," \r\n\r\n " );
181
134
std::istreamresponse_stream (&response_buffer);
182
135
string_type header_line, name;
@@ -200,8 +153,8 @@ namespace boost { namespace network { namespace http {
200
153
};
201
154
};
202
155
203
- void read_body (basic_response<tag > & response_, boost::asio::ip::tcp::socket & socket, boost::asio::streambuf & response_buffer)const {
204
- typename ostringstream<tag >::type body_stream;
156
+ void read_body (basic_response<Tag > & response_, boost::asio::ip::tcp::socket & socket, boost::asio::streambuf & response_buffer)const {
157
+ typename ostringstream<Tag >::type body_stream;
205
158
206
159
if (response_buffer.size () >0 )
207
160
body_stream << &response_buffer;
@@ -216,17 +169,17 @@ namespace boost { namespace network { namespace http {
216
169
response_ <<body (body_stream.str ());
217
170
};
218
171
219
- responseconst sync_request_skeleton (basic_request<tag >const & request_, string_type method,bool get_body) {
172
+ responseconst sync_request_skeleton (basic_request<Tag >const & request_, string_type method,bool get_body) {
220
173
using boost::asio::ip::tcp;
221
174
222
- basic_request<tag >request_copy (request_);
223
- basic_response<tag > response_;
175
+ basic_request<Tag >request_copy (request_);
176
+ basic_response<Tag > response_;
224
177
do {
225
178
tcp::socketsocket (service_);
226
179
init_socket (socket, request_copy.host (), boost::lexical_cast<string_type>(request_copy.port ()));
227
180
send_request (socket, method, request_copy);
228
181
229
- response_ = basic_response<tag >();
182
+ response_ = basic_response<Tag >();
230
183
response_ <<source (request_copy.host ());
231
184
232
185
boost::asio::streambuf response_buffer;
@@ -269,66 +222,66 @@ namespace boost { namespace network { namespace http {
269
222
};
270
223
271
224
basic_client ()
272
- :service_( ),resolver_( service_),cache_resolved_( false ), follow_redirect_(false )
225
+ :resolver_base( false ), service_( ),resolver_(service_ ), follow_redirect_(false )
273
226
{};
274
227
275
228
explicit basic_client (cache_resolved_type (*)())
276
- :service_( ),resolver_( service_),cache_resolved_( true ), follow_redirect_(false )
229
+ :resolver_base( true ), service_( ),resolver_(service_ ), follow_redirect_(false )
277
230
{};
278
231
279
232
explicit basic_client (follow_redirect_type (*)())
280
- :service_( ),resolver_( service_),cache_resolved_( false ), follow_redirect_(true )
233
+ :resolver_base( false ), service_( ),resolver_(service_ ), follow_redirect_(true )
281
234
{};
282
235
283
236
basic_client (cache_resolved_type (*)(), follow_redirect_type (*)())
284
- :service_( ),resolver_( service_),cache_resolved_( true ), follow_redirect_(true )
237
+ :resolver_base( false ), service_( ),resolver_(service_ ), follow_redirect_(true )
285
238
{};
286
239
287
240
void clear_resolved_cache () {
288
- endpoint_cache_.clear ();
241
+ resolver_base:: endpoint_cache_.clear ();
289
242
}
290
243
291
- responseconst head (basic_request<tag >const & request_) {
244
+ responseconst head (basic_request<Tag >const & request_) {
292
245
return sync_request_skeleton (request_," HEAD" ,false );
293
246
};
294
247
295
- responseconst get (basic_request<tag >const & request_) {
248
+ responseconst get (basic_request<Tag >const & request_) {
296
249
return sync_request_skeleton (request_," GET" ,true );
297
250
};
298
251
299
- responseconst post (basic_request<tag >const & request_) {
252
+ responseconst post (basic_request<Tag >const & request_) {
300
253
return sync_request_skeleton (request_," POST" ,true );
301
254
};
302
255
303
- responseconst post (basic_request<tag >const & request_, string_typeconst & content_type, string_typeconst & body_) {
304
- basic_request<tag > request_copy = request_;
256
+ responseconst post (basic_request<Tag >const & request_, string_typeconst & content_type, string_typeconst & body_) {
257
+ basic_request<Tag > request_copy = request_;
305
258
request_copy <<body (body_)
306
259
<<header (" Content-Type" , content_type)
307
260
<<header (" Content-Length" , boost::lexical_cast<string_type>(body_.size ()));
308
261
return post (request_copy);
309
262
};
310
263
311
- responseconst post (basic_request<tag >const & request_, string_typeconst & body_) {
264
+ responseconst post (basic_request<Tag >const & request_, string_typeconst & body_) {
312
265
return post (request_," x-application/octet-stream" , body_);
313
266
};
314
267
315
- responseconst put (basic_request<tag >const & request_) {
268
+ responseconst put (basic_request<Tag >const & request_) {
316
269
return sync_request_skeleton (request_," PUT" ,true );
317
270
};
318
271
319
- responseconst put (basic_request<tag >const & request_, string_typeconst & body_) {
272
+ responseconst put (basic_request<Tag >const & request_, string_typeconst & body_) {
320
273
return put (request_," x-application/octet-stream" , body_);
321
274
};
322
275
323
- responseconst put (basic_request<tag >const & request_, string_typeconst & content_type, string_typeconst & body_) {
324
- basic_request<tag > request_copy = request_;
276
+ responseconst put (basic_request<Tag >const & request_, string_typeconst & content_type, string_typeconst & body_) {
277
+ basic_request<Tag > request_copy = request_;
325
278
request_copy <<body (body_)
326
279
<<header (" Content-Type" , content_type)
327
280
<<header (" Content-Length" , boost::lexical_cast<string_type>(body_.size ()));
328
281
return put (request_copy);
329
282
};
330
283
331
- responseconst delete_ (basic_request<tag >const & request_) {
284
+ responseconst delete_ (basic_request<Tag >const & request_) {
332
285
return sync_request_skeleton (request_," DELETE" ,true );
333
286
};
334
287