10
10
11
11
#include < boost/unordered_map.hpp>
12
12
#include < boost/shared_ptr.hpp>
13
+ #include < utility>
13
14
#include < boost/network/protocol/http/detail/connection_helper.hpp>
14
15
#include < boost/network/protocol/http/impl/sync_connection_base.hpp>
16
+ #include < boost/algorithm/string/predicate.hpp>
17
+
18
+ #include < iostream>
15
19
16
20
#ifndef BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT
17
21
#define BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT 5
@@ -29,14 +33,22 @@ namespace boost { namespace network { namespace http {
29
33
typedef function<typename resolver_base::resolver_iterator_pair (resolver_type &, string_type const &, string_type const &)> resolver_function_type;
30
34
31
35
struct connection_impl {
36
+ typedef function<shared_ptr<connection_impl>(resolver_type &,basic_request<Tag> const &)> get_connection_function;
32
37
33
- connection_impl (resolver_type & resolver, bool follow_redirect, string_type const & host, string_type const & port, resolver_function_type resolve, pooled_connection_policy & source)
34
- : pimpl(impl::sync_connection_base<Tag,version_major,version_minor>::new_connection(resolver, resolve)), source_(source) {}
38
+ connection_impl (resolver_type & resolver, bool follow_redirect, string_type const & host, string_type const & port, resolver_function_type resolve, get_connection_function get_connection, bool https)
39
+ : pimpl(impl::sync_connection_base<Tag,version_major,version_minor>::new_connection(resolver, resolve, https))
40
+ , resolver_(resolver)
41
+ , connection_follow_redirect_(follow_redirect)
42
+ , get_connection_(get_connection) {}
35
43
36
44
basic_response<Tag> send_request (string_type const & method, basic_request<Tag> request_, bool get_body) {
37
45
return send_request_recursive (method, request_, get_body, 0 );
38
46
}
39
47
48
+ ~connection_impl () {
49
+ pimpl.reset ();
50
+ }
51
+
40
52
private:
41
53
42
54
basic_response<Tag> send_request_recursive (string_type const & method, basic_request<Tag> request_, bool get_body, int count) {
@@ -45,49 +57,64 @@ namespace boost { namespace network { namespace http {
45
57
46
58
basic_response<Tag> response_;
47
59
// check if the socket is open first
48
- if (!pimpl->socket_ . is_open ()) {
60
+ if (!pimpl->is_open ()) {
49
61
pimpl->init_socket (request_.host (), lexical_cast<string_type>(request_.port ()));
50
62
}
63
+ std::cerr << " Sending request to " << request_.host () << " ...\n " ;
51
64
pimpl->send_request_impl (method, request_);
52
65
response_ = basic_response<Tag>();
53
66
response_ << source (request_.host ());
54
67
55
68
boost::asio::streambuf response_buffer;
69
+ std::cerr << " Reading status from " << request_.host () << " ...\n " ;
56
70
pimpl->read_status (response_, response_buffer);
71
+ std::cerr << " Reading headers from " << request_.host () << " ...\n " ;
57
72
pimpl->read_headers (response_, response_buffer);
58
- if (get_body) pimpl->read_body (response_, response_buffer);
73
+ if (
74
+ get_body && response_.status () != 304
75
+ && (response_.status () != 204 )
76
+ && not (response_.status () >= 100 && response_.status () <= 199 )
77
+ ) {
78
+ std::cerr << " Reading body from " << request_.host () << " ...\n " ;
79
+ pimpl->read_body (response_, response_buffer);
80
+ }
59
81
60
- if (follow_redirect_ ) {
82
+ if (connection_follow_redirect_ ) {
61
83
boost::uint16_t status = response_.status ();
62
84
if (status >= 300 && status <= 307 ) {
63
85
typename headers_range<basic_response<Tag> >::type location_range = headers (response_)[" Location" ];
64
86
typename range_iterator<typename headers_range<basic_request<Tag> >::type>::type location_header = begin (location_range);
65
87
if (location_header != end (location_range)) {
66
88
request_.uri (location_header->second );
67
89
connection_ptr connection_;
68
- connection_ = source_. get_connection (pimpl-> resolver_ , request_);
90
+ connection_ = get_connection_ ( resolver_, request_);
69
91
return connection_->send_request_recursive (method, request_, get_body, ++count);
70
92
} else throw std::runtime_error (" Location header not defined in redirect response." );
71
93
}
72
94
}
73
95
96
+ typename headers_range<basic_response<Tag> >::type connection_range = headers (response_)[" Connection" ];
97
+ if (!empty (connection_range) && begin (connection_range)->second == string_type (" close" )) {
98
+ std::cerr << " Before closing socket for " << request_.host () << " :" << request_.port () << " ...\n " ;
99
+ pimpl->close_socket ();
100
+ std::cerr << " After closing socket for " << request_.host () << " :" << request_.port () << " ...\n " ;
101
+ }
102
+
74
103
return response_;
75
104
}
105
+
76
106
shared_ptr<http::impl::sync_connection_base<Tag,version_major,version_minor> > pimpl;
77
- pooled_connection_policy & source_;
78
- template <class T , unsigned vma, unsigned vmi> friend struct pooled_connection ;
107
+ resolver_type & resolver_;
108
+ bool connection_follow_redirect_;
109
+ get_connection_function get_connection_;
79
110
};
80
111
81
112
typedef shared_ptr<connection_impl> connection_ptr;
82
113
83
- private:
84
-
85
114
typedef unordered_map<string_type, connection_ptr> host_connection_map;
86
115
host_connection_map host_connections;
87
116
bool follow_redirect_;
88
117
89
- protected:
90
-
91
118
connection_ptr get_connection (resolver_type & resolver, basic_request<Tag> const & request_) {
92
119
string_type index = (request_.host () + ' :' ) + lexical_cast<string_type>(request_.port ());
93
120
connection_ptr connection_;
@@ -104,15 +131,24 @@ namespace boost { namespace network { namespace http {
104
131
this ,
105
132
_1, _2, _3
106
133
)
107
- , *this
134
+ , bind (
135
+ &pooled_connection_policy<Tag,version_major,version_minor>::get_connection,
136
+ this ,
137
+ _1, _2
138
+ )
139
+ , boost::iequals (request_.protocol (), string_type (" https" ))
108
140
)
109
141
);
110
- host_connections.insert (index , connection_);
142
+ host_connections.insert (std::make_pair ( index , connection_) );
111
143
return connection_;
112
144
}
113
145
return it->second ;
114
146
}
115
147
148
+ void cleanup () {
149
+ host_connection_map ().swap (host_connections);
150
+ }
151
+
116
152
pooled_connection_policy (bool cache_resolved, bool follow_redirect)
117
153
: resolver_base(cache_resolved), host_connections(), follow_redirect_(follow_redirect) {}
118
154
0 commit comments