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

Commit0aed5d1

Browse files
committed
Implementing support for HTTP 1.1 chunked encoding, and keepalive connections.
1 parentc3eeb92 commit0aed5d1

File tree

5 files changed

+125
-30
lines changed

5 files changed

+125
-30
lines changed

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

Lines changed: 61 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include<boost/network/protocol/http/traits/resolver_policy.hpp>
1010
#include<boost/network/protocol/http/detail/connection_helper.hpp>
11+
#include<boost/network/traits/ostringstream.hpp>
12+
#include<boost/network/traits/istringstream.hpp>
1113
#include<boost/asio/ssl.hpp>
1214
#include<boost/tuple/tuple.hpp>
1315

@@ -97,35 +99,75 @@ namespace boost { namespace network { namespace http { namespace impl {
9799
voidread_body(Socket & socket_, basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
98100
typename ostringstream<Tag>::type body_stream;
99101

100-
if (response_buffer.size() >0)
101-
body_stream << &response_buffer;
102-
103102
boost::system::error_code error;
104-
if (!connection_keepalive<Tag>::value) {
103+
// TODO tag dispatch based on whether it's HTTP 1.0 or HTTP 1.1
104+
if (version_major ==1 && version_minor ==0) {
105+
if (response_buffer.size() >0)
106+
body_stream << &response_buffer;
107+
105108
while (boost::asio::read(socket_, response_buffer,boost::asio::transfer_at_least(1), error)) {
106109
body_stream << &response_buffer;
107110
}
108-
}else {
111+
}elseif (version_major ==1 && version_minor ==1){
109112
// look for the content-length header
110113
typename headers_range<basic_response<Tag> >::type content_length_range =
111114
headers(response_)["Content-Length"];
112-
if (empty(content_length_range))
113-
throwstd::runtime_error("Unsupported response, missing 'Content-Length' header.");
114-
size_t length = lexical_cast<size_t>(begin(content_length_range)->second);
115-
std::cerr <<"Before reading body of size" << length <<"...\n";
116-
size_t bytes_read =0;
117-
while ((bytes_read =boost::asio::read(socket_, response_buffer,boost::asio::transfer_at_least(1), error))) {
118-
body_stream << &response_buffer;
119-
length -= bytes_read;
120-
if ((length <=0)or error)
121-
break;
115+
if (empty(content_length_range)) {
116+
typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
117+
headers(response_)["Transfer-Encoding"];
118+
if (empty(transfer_encoding_range))throwstd::runtime_error("Missing Transfer-Encoding Header from response.");
119+
if (boost::iequals(begin(transfer_encoding_range)->second,"chunked")) {
120+
bool stopping =false;
121+
do {
122+
std::size_t chunk_size_line =read_until(socket_, response_buffer,"\r\n", error);
123+
if ((chunk_size_line ==0) && (error != boost::asio::error::eof))throwboost::system::system_error(error);
124+
std::size_t chunk_size =0;
125+
string_type data;
126+
{
127+
std::istreamchunk_stream(&response_buffer);
128+
std::getline(chunk_stream, data);
129+
typename istringstream<Tag>::typechunk_size_stream(data);
130+
chunk_size_stream >> std::hex >> chunk_size;
131+
}
132+
if (chunk_size ==0) {
133+
stopping =true;
134+
if (!read_until(socket_, response_buffer,"\r\n", error) && (error != boost::asio::error::eof))
135+
throwboost::system::system_error(error);
136+
}else {
137+
bool stopping_inner =false;
138+
do {
139+
std::size_t chunk_bytes_read =read(socket_, response_buffer,boost::asio::transfer_at_least(chunk_size +2), error);
140+
if (chunk_bytes_read ==0) {
141+
if (error != boost::asio::error::eof)throwboost::system::system_error(error);
142+
stopping_inner =true;
143+
}
144+
145+
std::istreambuf_iterator<char> eos;
146+
std::istreambuf_iterator<char>stream_iterator(&response_buffer);
147+
for (; chunk_size >0 && stream_iterator != eos; --chunk_size)
148+
body_stream << *stream_iterator++;
149+
response_buffer.consume(2);
150+
}while (!stopping_inner && chunk_size !=0);
151+
152+
if (chunk_size !=0)
153+
throwstd::runtime_error("Size mismatch between tranfer encoding chunk data size and declared chunk size.");
154+
}
155+
}while (!stopping);
156+
}elsethrowstd::runtime_error("Unsupported Transfer-Encoding.");
157+
}else {
158+
size_t length = lexical_cast<size_t>(begin(content_length_range)->second);
159+
size_t bytes_read =0;
160+
while ((bytes_read =boost::asio::read(socket_, response_buffer,boost::asio::transfer_at_least(1), error))) {
161+
body_stream << &response_buffer;
162+
length -= bytes_read;
163+
if ((length <=0)or error)
164+
break;
165+
}
122166
}
123-
std::cerr <<"After reading body of size" << length <<"...\n";
167+
}else {
168+
throwstd::runtime_error("Unsupported HTTP version number.");
124169
}
125170

126-
if (error != boost::asio::error::eof)
127-
throwboost::system::system_error(error);
128-
129171
response_ <<body(body_stream.str());
130172
}
131173

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

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,10 @@
1010

1111
#include<boost/unordered_map.hpp>
1212
#include<boost/shared_ptr.hpp>
13-
#include<utility>
1413
#include<boost/network/protocol/http/detail/connection_helper.hpp>
1514
#include<boost/network/protocol/http/impl/sync_connection_base.hpp>
1615
#include<boost/algorithm/string/predicate.hpp>
17-
18-
#include<iostream>
16+
#include<utility>
1917

2018
#ifndef BOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT
2119
#defineBOOST_NETWORK_HTTP_MAXIMUM_REDIRECT_COUNT5
@@ -60,22 +58,18 @@ namespace boost { namespace network { namespace http {
6058
if (!pimpl->is_open()) {
6159
pimpl->init_socket(request_.host(), lexical_cast<string_type>(request_.port()));
6260
}
63-
std::cerr <<"Sending request to" << request_.host() <<"...\n";
6461
pimpl->send_request_impl(method, request_);
6562
response_ = basic_response<Tag>();
6663
response_ <<source(request_.host());
6764

6865
boost::asio::streambuf response_buffer;
69-
std::cerr <<"Reading status from" << request_.host() <<"...\n";
7066
pimpl->read_status(response_, response_buffer);
71-
std::cerr <<"Reading headers from" << request_.host() <<"...\n";
7267
pimpl->read_headers(response_, response_buffer);
7368
if (
7469
get_body && response_.status() !=304
7570
&& (response_.status() !=204)
7671
&&not (response_.status() >=100 && response_.status() <=199)
7772
) {
78-
std::cerr <<"Reading body from" << request_.host() <<"...\n";
7973
pimpl->read_body(response_, response_buffer);
8074
}
8175

@@ -95,9 +89,7 @@ namespace boost { namespace network { namespace http {
9589

9690
typename headers_range<basic_response<Tag> >::type connection_range =headers(response_)["Connection"];
9791
if (!empty(connection_range) &&begin(connection_range)->second ==string_type("close")) {
98-
std::cerr <<"Before closing socket for" << request_.host() <<":" << request_.port() <<"...\n";
9992
pimpl->close_socket();
100-
std::cerr <<"After closing socket for" << request_.host() <<":" << request_.port() <<"...\n";
10193
}
10294

10395
return response_;
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copyright (c) Glyn Matthews 2009.
2+
// Copyright (c) Dean Michael Berris 2009.
3+
// Distributed under the Boost Software License, Version 1.0.
4+
// (See accompanying file LICENSE_1_0.txt or copy at
5+
// http://www.boost.org/LICENSE_1_0.txt)
6+
7+
#ifndef BOOST_NETWORK_TRAITS_ISTRINGSTREAM_INC
8+
#defineBOOST_NETWORK_TRAITS_ISTRINGSTREAM_INC
9+
10+
#include<sstream>
11+
#include<boost/network/tags.hpp>
12+
13+
namespaceboost {namespacenetwork {
14+
15+
template<classTag>
16+
structunsupported_tag;
17+
18+
template<classTag>
19+
structistringstream {
20+
typedef unsupported_tag<Tag> type;
21+
};
22+
23+
template<>
24+
structistringstream<tags::default_string> {
25+
typedef std::istringstream type;
26+
};
27+
28+
29+
template<>
30+
structistringstream<tags::default_wstring> {
31+
typedef std::wistringstream type;
32+
};
33+
34+
template<>
35+
structistringstream<tags::http_default_8bit_tcp_resolve> {
36+
typedef std::istringstream type;
37+
};
38+
39+
template<>
40+
structistringstream<tags::http_default_8bit_udp_resolve> {
41+
typedef std::istringstream type;
42+
};
43+
44+
template<>
45+
structistringstream<tags::http_keepalive_8bit_tcp_resolve> {
46+
typedef std::istringstream type;
47+
};
48+
49+
template<>
50+
structistringstream<tags::http_keepalive_8bit_udp_resolve> {
51+
typedef std::istringstream type;
52+
};
53+
54+
}// namespace network
55+
56+
}// namespace boost
57+
58+
59+
#endif// BOOST_NETWORK_TRAITS_ISTRINGSTREAM_INC
60+

‎libs/network/example/http_client.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ int main(int argc, char * argv[]) {
5757
usingnamespaceboost::network;
5858

5959
http::basic_client<tags::http_keepalive_8bit_udp_resolve,1,1>::requestrequest(source);
60+
request <<header("Connection","close");
6061
http::basic_client<tags::http_keepalive_8bit_udp_resolve,1,1>client(
6162
http::basic_client<tags::http_keepalive_8bit_udp_resolve,1,1>::follow_redirects
6263
);

‎libs/network/example/simple_wget.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ main(int argc, char *argv[]) {
4747
try {
4848
http::client client;
4949
constchar *uri = argv[1];
50-
http::requestrequest(uri);
51-
http::response response = client.get(request);
50+
http::client::requestrequest(uri);
51+
http::client::response response = client.get(request);
5252

5353
std::string filename =get_filename(uri);
5454
std::cout <<"Saving to:" << filename << std::endl;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp