Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4831538

Browse files
committed
Implementing keep-alive connections in HTTP 1.1, but no chunked transfer encoding support yet.
1 parent288d7ae commit4831538

File tree

14 files changed

+182
-28
lines changed

14 files changed

+182
-28
lines changed

‎boost/network/protocol/http/client.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ namespace boost { namespace network { namespace http {
7171
//
7272
// =================================================================
7373

74+
~basic_client() {
75+
connection_base::cleanup();
76+
}
77+
7478
voidclear_resolved_cache() {
7579
connection_base::endpoint_cache_.clear();
7680
}

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include<boost/network/version.hpp>
1010
#include<boost/foreach.hpp>
11+
#include<boost/network/protocol/http/traits/connection_keepalive.hpp>
1112

1213
namespaceboost {namespacenetwork {namespacehttp {namespacedetail {
1314

@@ -47,6 +48,10 @@ namespace boost { namespace network { namespace http { namespace detail {
4748
<<"Host:" << request_.host() <<"\r\n"
4849
<<"Accept: */*\r\n";
4950

51+
if (version_major ==1 && version_minor ==1)
52+
request_stream
53+
<<"Accept-Encoding: identity;q=1.0, *;q=0\r\n";// only accept identity encoding
54+
5055
typename headers_range<http::basic_request<Tag> >::type range =headers(request_);
5156
BOOST_FOREACH(typename headers_range<http::basic_request<Tag> >::type::value_typeconst & header, range) {
5257
request_stream << header.first <<":" << header.second <<"\r\n";
@@ -55,8 +60,12 @@ namespace boost { namespace network { namespace http { namespace detail {
5560
range =headers(request_)["user-agent"];
5661
if (empty(range)) request_stream <<"User-Agent: cpp-netlib/" << BOOST_NETLIB_VERSION <<"\r\n";
5762

63+
if (!connection_keepalive<Tag>::value) {
64+
request_stream
65+
<<"Connection: close\r\n";
66+
}
5867
request_stream
59-
<<"Connection: close\r\n\r\n";
68+
<<"\r\n";
6069

6170
string_type body_ =body(request_);
6271
if (!body_.empty())

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

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ namespace boost { namespace network { namespace http { namespace impl {
3030
voidread_status(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {}
3131
voidread_headers(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {}
3232
voidread_body(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {}
33+
boolis_open() {return socket_.lowest_layer().is_open(); }
34+
voidclose_socket() {if (is_open()) { socket_.lowest_layer().close(); } }
3335
~https_sync_connection() {}
3436
private:
3537
resolver_type & resolver_;
@@ -129,15 +131,38 @@ namespace boost { namespace network { namespace http { namespace impl {
129131
body_stream << &response_buffer;
130132

131133
boost::system::error_code error;
132-
while (boost::asio::read(socket_, response_buffer,boost::asio::transfer_at_least(1), error))
133-
body_stream << &response_buffer;
134+
if (!connection_keepalive<Tag>::value) {
135+
while (boost::asio::read(socket_, response_buffer,boost::asio::transfer_at_least(1), error)) {
136+
body_stream << &response_buffer;
137+
}
138+
}else {
139+
// look for the content-length header
140+
typename headers_range<basic_response<Tag> >::type content_length_range =
141+
headers(response_)["Content-Length"];
142+
if (empty(content_length_range))
143+
throwstd::runtime_error("Unsupported response, missing 'Content-Length' header.");
144+
size_t length = lexical_cast<size_t>(begin(content_length_range)->second);
145+
std::cerr <<"Before reading body of size" << length <<"...\n";
146+
size_t bytes_read =0;
147+
while ((bytes_read =boost::asio::read(socket_, response_buffer,boost::asio::transfer_at_least(1), error))) {
148+
body_stream << &response_buffer;
149+
length -= bytes_read;
150+
if ((length <=0)or error)
151+
break;
152+
}
153+
std::cerr <<"After reading body of size" << length <<"...\n";
154+
}
134155

135156
if (error != boost::asio::error::eof)
136157
throwboost::system::system_error(error);
137158

138159
response_ <<body(body_stream.str());
139160
}
140161

162+
boolis_open() {return socket_.is_open(); }
163+
164+
voidclose_socket() {if (is_open()) { socket_.close(); } }
165+
141166
private:
142167

143168
resolver_type & resolver_;
@@ -165,6 +190,8 @@ namespace boost { namespace network { namespace http { namespace impl {
165190
virtualvoidread_status(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) = 0;
166191
virtualvoidread_headers(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) = 0;
167192
virtualvoidread_body(basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) = 0;
193+
virtualboolis_open() = 0;
194+
virtualvoidclose_socket() = 0;
168195
virtual~sync_connection_base() {}
169196
protected:
170197
sync_connection_base() {}

‎boost/network/protocol/http/policies/pooled_connection.hpp

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,12 @@
1010

1111
#include<boost/unordered_map.hpp>
1212
#include<boost/shared_ptr.hpp>
13+
#include<utility>
1314
#include<boost/network/protocol/http/detail/connection_helper.hpp>
1415
#include<boost/network/protocol/http/impl/sync_connection_base.hpp>
16+
#include<boost/algorithm/string/predicate.hpp>
17+
18+
#include<iostream>
1519

1620
#ifndef BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT
1721
#defineBOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT5
@@ -29,14 +33,22 @@ namespace boost { namespace network { namespace http {
2933
typedef function<typenameresolver_base::resolver_iterator_pair(resolver_type &, string_typeconst &, string_typeconst &)> resolver_function_type;
3034

3135
structconnection_impl {
36+
typedef function<shared_ptr<connection_impl>(resolver_type &,basic_request<Tag>const &)> get_connection_function;
3237

33-
connection_impl(resolver_type & resolver,bool follow_redirect, string_typeconst & host, string_typeconst & 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_typeconst & host, string_typeconst & 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) {}
3543

3644
basic_response<Tag>send_request(string_typeconst & method, basic_request<Tag> request_,bool get_body) {
3745
returnsend_request_recursive(method, request_, get_body,0);
3846
}
3947

48+
~connection_impl () {
49+
pimpl.reset();
50+
}
51+
4052
private:
4153

4254
basic_response<Tag>send_request_recursive(string_typeconst & method, basic_request<Tag> request_,bool get_body,int count) {
@@ -45,49 +57,64 @@ namespace boost { namespace network { namespace http {
4557

4658
basic_response<Tag> response_;
4759
// check if the socket is open first
48-
if (!pimpl->socket_.is_open()) {
60+
if (!pimpl->is_open()) {
4961
pimpl->init_socket(request_.host(), lexical_cast<string_type>(request_.port()));
5062
}
63+
std::cerr <<"Sending request to" << request_.host() <<"...\n";
5164
pimpl->send_request_impl(method, request_);
5265
response_ = basic_response<Tag>();
5366
response_ <<source(request_.host());
5467

5568
boost::asio::streambuf response_buffer;
69+
std::cerr <<"Reading status from" << request_.host() <<"...\n";
5670
pimpl->read_status(response_, response_buffer);
71+
std::cerr <<"Reading headers from" << request_.host() <<"...\n";
5772
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+
}
5981

60-
if (follow_redirect_) {
82+
if (connection_follow_redirect_) {
6183
boost::uint16_t status = response_.status();
6284
if (status >=300 && status <=307) {
6385
typename headers_range<basic_response<Tag> >::type location_range =headers(response_)["Location"];
6486
typename range_iterator<typename headers_range<basic_request<Tag> >::type>::type location_header =begin(location_range);
6587
if (location_header !=end(location_range)) {
6688
request_.uri(location_header->second);
6789
connection_ptr connection_;
68-
connection_ =source_.get_connection(pimpl->resolver_, request_);
90+
connection_ =get_connection_(resolver_, request_);
6991
return connection_->send_request_recursive(method, request_, get_body, ++count);
7092
}elsethrowstd::runtime_error("Location header not defined in redirect response.");
7193
}
7294
}
7395

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+
74103
return response_;
75104
}
105+
76106
shared_ptr<http::impl::sync_connection_base<Tag,version_major,version_minor> > pimpl;
77-
pooled_connection_policy & source_;
78-
template<classT,unsigned vma,unsigned vmi>friendstructpooled_connection;
107+
resolver_type & resolver_;
108+
bool connection_follow_redirect_;
109+
get_connection_function get_connection_;
79110
};
80111

81112
typedef shared_ptr<connection_impl> connection_ptr;
82113

83-
private:
84-
85114
typedef unordered_map<string_type, connection_ptr> host_connection_map;
86115
host_connection_map host_connections;
87116
bool follow_redirect_;
88117

89-
protected:
90-
91118
connection_ptrget_connection(resolver_type & resolver, basic_request<Tag>const & request_) {
92119
string_type index = (request_.host() +':') + lexical_cast<string_type>(request_.port());
93120
connection_ptr connection_;
@@ -104,15 +131,24 @@ namespace boost { namespace network { namespace http {
104131
this,
105132
_1, _2, _3
106133
)
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"))
108140
)
109141
);
110-
host_connections.insert(index, connection_);
142+
host_connections.insert(std::make_pair(index, connection_));
111143
return connection_;
112144
}
113145
return it->second;
114146
}
115147

148+
voidcleanup() {
149+
host_connection_map().swap(host_connections);
150+
}
151+
116152
pooled_connection_policy(bool cache_resolved,bool follow_redirect)
117153
: resolver_base(cache_resolved), host_connections(), follow_redirect_(follow_redirect) {}
118154

‎boost/network/protocol/http/policies/simple_connection.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ namespace boost { namespace network { namespace http {
9292
return connection_;
9393
}
9494

95+
voidcleanup() { }
96+
9597
simple_connection_policy(bool cache_resolved,bool follow_redirect)
9698
: resolver_base(cache_resolved), follow_redirect_(follow_redirect) {}
9799

‎boost/network/protocol/http/traits.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
// Convenience header for including different traits implementations.
1414
#include<boost/network/protocol/http/traits/message_traits.hpp>
1515
#include<boost/network/protocol/http/traits/parser_traits.hpp>
16+
#include<boost/network/protocol/http/traits/connection_keepalive.hpp>
1617

1718
#endif// BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_HPP
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218
2+
#defineBOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218
3+
4+
#include<boost/network/tags.hpp>
5+
6+
namespaceboost {namespacenetwork {namespacehttp {
7+
8+
template<classTag>
9+
structconnection_keepalive {
10+
staticboolconst value =false;
11+
};
12+
13+
template<>
14+
structconnection_keepalive<tags::http_keepalive_8bit_udp_resolve> {
15+
staticboolconst value =true;
16+
};
17+
18+
template<>
19+
structconnection_keepalive<tags::http_keepalive_8bit_tcp_resolve> {
20+
staticboolconst value =true;
21+
};
22+
23+
}/* http*/
24+
25+
}/* network*/
26+
27+
}/* boost*/
28+
29+
#endif// BOOST_NETWORK_PROTOCOL_HTTP_TRAITS_CONECTION_KEEPALIVE_20091218
30+

‎boost/network/protocol/http/traits/resolver.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@ namespace boost { namespace network { namespace http {
2828
typedef boost::asio::ip::udp::resolver type;
2929
};
3030

31+
template<>
32+
structresolver<tags::http_keepalive_8bit_tcp_resolve> {
33+
typedef boost::asio::ip::tcp::resolver type;
34+
};
35+
36+
template<>
37+
structresolver<tags::http_keepalive_8bit_udp_resolve> {
38+
typedef boost::asio::ip::udp::resolver type;
39+
};
40+
3141
}// namespace http
3242

3343
}// namespace network

‎boost/network/protocol/http/traits/resolver_policy.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ namespace boost { namespace network { namespace http {
2929
typedef policies::sync_resolver<tags::http_default_8bit_udp_resolve> type;
3030
};
3131

32+
template<>
33+
structresolver_policy<tags::http_keepalive_8bit_udp_resolve> {
34+
typedef policies::sync_resolver<tags::http_keepalive_8bit_udp_resolve> type;
35+
};
36+
37+
template<>
38+
structresolver_policy<tags::http_keepalive_8bit_tcp_resolve> {
39+
typedef policies::sync_resolver<tags::http_keepalive_8bit_tcp_resolve> type;
40+
};
41+
3242
}// namespace http
3343

3444
}// namespace network

‎boost/network/traits/ostringstream.hpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Copyright (c) Glyn Matthews 2009.
2+
// Copyright (c) Dean Michael Berris 2009.
23
// Distributed under the Boost Software License, Version 1.0.
34
// (See accompanying file LICENSE_1_0.txt or copy at
45
// http://www.boost.org/LICENSE_1_0.txt)
@@ -11,14 +12,14 @@
1112

1213
namespaceboost {namespacenetwork {
1314

14-
template<
15-
classTag
16-
>
15+
template<classTag>
16+
structunsupported_tag;
17+
18+
template<classTag>
1719
structostringstream {
18-
typedefvoid type;
20+
typedefunsupported_tag<Tag> type;
1921
};
2022

21-
2223
template<>
2324
structostringstream<tags::default_string> {
2425
typedef std::ostringstream type;
@@ -40,6 +41,16 @@ namespace boost { namespace network {
4041
typedef std::ostringstream type;
4142
};
4243

44+
template<>
45+
structostringstream<tags::http_keepalive_8bit_tcp_resolve> {
46+
typedef std::ostringstream type;
47+
};
48+
49+
template<>
50+
structostringstream<tags::http_keepalive_8bit_udp_resolve> {
51+
typedef std::ostringstream type;
52+
};
53+
4354
}// namespace network
4455

4556
}// namespace boost

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp