11
2- // Copyright Dean Michael Berris 2007-2008 .
2+ // Copyright Dean Michael Berris 2007-2009 .
33// Distributed under the Boost Software License, Version 1.0.
44// (See accompanying file LICENSE_1_0.txt or copy at
55// http://www.boost.org/LICENSE_1_0.txt)
88#define __NETWORK_PROTOCOL_HTTP_CLIENT_20070908_1_HPP__
99
1010#ifndef BOOST_NETLIB_VERSION
11- #define BOOST_NETLIB_VERSION " 0.3 "
11+ #define BOOST_NETLIB_VERSION " 0.5 "
1212#endif
1313
1414#include < boost/network/traits/ostringstream.hpp>
1515#include < boost/network/protocol/http/message.hpp>
1616#include < boost/network/protocol/http/response.hpp>
1717#include < boost/network/protocol/http/request.hpp>
18+ #include < boost/network/protocol/http/traits/resolver_policy.hpp>
1819#include < boost/asio.hpp>
1920#include < boost/lexical_cast.hpp>
2021#include < boost/algorithm/string/classification.hpp>
2930
3031namespace boost {namespace network {namespace http {
3132
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 {
3435
3536private:
37+ typedef typename resolver_policy<Tag>::type resolver_base;
3638 boost::asio::io_service service_;
37- boost::asio::ip::tcp::resolver resolver_;
38- bool cache_resolved_;
39+ typename resolver_base::resolver_type resolver_;
3940bool follow_redirect_;
4041
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;
8943
9044void init_socket (boost::asio::ip::tcp::socket & socket_, string_typeconst & hostname, string_typeconst & port) {
9145using boost::asio::ip::tcp;
9246
9347 boost::system::error_code error = boost::asio::error::host_not_found;
9448
9549 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);
9751
9852while (error && endpoint_iterator != end) {
9953 socket_.close ();
@@ -104,7 +58,7 @@ namespace boost { namespace network { namespace http {
10458throw boost::system::system_error (error);
10559 };
10660
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 {
10862 std::ostreamrequest_stream (&request_buffer);
10963
11064 request_stream
@@ -139,8 +93,7 @@ namespace boost { namespace network { namespace http {
13993 };
14094
14195 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 " ;
14497
14598 request_stream
14699 <<" Connection: close\r\n\r\n " ;
@@ -150,13 +103,13 @@ namespace boost { namespace network { namespace http {
150103 request_stream << body_;
151104 };
152105
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 {
154107 boost::asio::streambuf request_buffer;
155108create_request (request_buffer, method, request_);
156109write (socket, request_buffer);
157110 };
158111
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 {
160113boost::asio::read_until (socket, response_buffer," \r\n " );
161114 std::istreamresponse_stream (&response_buffer);
162115 string_type http_version;
@@ -176,7 +129,7 @@ namespace boost { namespace network { namespace http {
176129 response_.status_message () = status_message;
177130 };
178131
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 {
180133boost::asio::read_until (socket, response_buffer," \r\n\r\n " );
181134 std::istreamresponse_stream (&response_buffer);
182135 string_type header_line, name;
@@ -200,8 +153,8 @@ namespace boost { namespace network { namespace http {
200153 };
201154 };
202155
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;
205158
206159if (response_buffer.size () >0 )
207160 body_stream << &response_buffer;
@@ -216,17 +169,17 @@ namespace boost { namespace network { namespace http {
216169 response_ <<body (body_stream.str ());
217170 };
218171
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) {
220173using boost::asio::ip::tcp;
221174
222- basic_request<tag >request_copy (request_);
223- basic_response<tag > response_;
175+ basic_request<Tag >request_copy (request_);
176+ basic_response<Tag > response_;
224177do {
225178 tcp::socketsocket (service_);
226179init_socket (socket, request_copy.host (), boost::lexical_cast<string_type>(request_copy.port ()));
227180send_request (socket, method, request_copy);
228181
229- response_ = basic_response<tag >();
182+ response_ = basic_response<Tag >();
230183 response_ <<source (request_copy.host ());
231184
232185 boost::asio::streambuf response_buffer;
@@ -269,66 +222,66 @@ namespace boost { namespace network { namespace http {
269222 };
270223
271224basic_client ()
272- :service_( ),resolver_( service_),cache_resolved_( false ), follow_redirect_(false )
225+ :resolver_base( false ), service_( ),resolver_(service_ ), follow_redirect_(false )
273226 {};
274227
275228explicit 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 )
277230 {};
278231
279232explicit 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 )
281234 {};
282235
283236basic_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 )
285238 {};
286239
287240void clear_resolved_cache () {
288- endpoint_cache_.clear ();
241+ resolver_base:: endpoint_cache_.clear ();
289242 }
290243
291- responseconst head (basic_request<tag >const & request_) {
244+ responseconst head (basic_request<Tag >const & request_) {
292245return sync_request_skeleton (request_," HEAD" ,false );
293246 };
294247
295- responseconst get (basic_request<tag >const & request_) {
248+ responseconst get (basic_request<Tag >const & request_) {
296249return sync_request_skeleton (request_," GET" ,true );
297250 };
298251
299- responseconst post (basic_request<tag >const & request_) {
252+ responseconst post (basic_request<Tag >const & request_) {
300253return sync_request_skeleton (request_," POST" ,true );
301254 };
302255
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_;
305258 request_copy <<body (body_)
306259 <<header (" Content-Type" , content_type)
307260 <<header (" Content-Length" , boost::lexical_cast<string_type>(body_.size ()));
308261return post (request_copy);
309262 };
310263
311- responseconst post (basic_request<tag >const & request_, string_typeconst & body_) {
264+ responseconst post (basic_request<Tag >const & request_, string_typeconst & body_) {
312265return post (request_," x-application/octet-stream" , body_);
313266 };
314267
315- responseconst put (basic_request<tag >const & request_) {
268+ responseconst put (basic_request<Tag >const & request_) {
316269return sync_request_skeleton (request_," PUT" ,true );
317270 };
318271
319- responseconst put (basic_request<tag >const & request_, string_typeconst & body_) {
272+ responseconst put (basic_request<Tag >const & request_, string_typeconst & body_) {
320273return put (request_," x-application/octet-stream" , body_);
321274 };
322275
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_;
325278 request_copy <<body (body_)
326279 <<header (" Content-Type" , content_type)
327280 <<header (" Content-Length" , boost::lexical_cast<string_type>(body_.size ()));
328281return put (request_copy);
329282 };
330283
331- responseconst delete_ (basic_request<tag >const & request_) {
284+ responseconst delete_ (basic_request<Tag >const & request_) {
332285return sync_request_skeleton (request_," DELETE" ,true );
333286 };
334287