|
8 | 8 |
|
9 | 9 | #include<boost/network/protocol/http/traits/resolver_policy.hpp> |
10 | 10 | #include<boost/network/protocol/http/detail/connection_helper.hpp> |
| 11 | +#include<boost/network/traits/ostringstream.hpp> |
| 12 | +#include<boost/network/traits/istringstream.hpp> |
11 | 13 | #include<boost/asio/ssl.hpp> |
12 | 14 | #include<boost/tuple/tuple.hpp> |
13 | 15 |
|
@@ -97,35 +99,75 @@ namespace boost { namespace network { namespace http { namespace impl { |
97 | 99 | voidread_body(Socket & socket_, basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) { |
98 | 100 | typename ostringstream<Tag>::type body_stream; |
99 | 101 |
|
100 | | -if (response_buffer.size() >0) |
101 | | - body_stream << &response_buffer; |
102 | | - |
103 | 102 | 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 | + |
105 | 108 | while (boost::asio::read(socket_, response_buffer,boost::asio::transfer_at_least(1), error)) { |
106 | 109 | body_stream << &response_buffer; |
107 | 110 | } |
108 | | - }else { |
| 111 | + }elseif (version_major ==1 && version_minor ==1){ |
109 | 112 | // look for the content-length header |
110 | 113 | typename headers_range<basic_response<Tag> >::type content_length_range = |
111 | 114 | 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 | + } |
122 | 166 | } |
123 | | - std::cerr <<"After reading body of size" << length <<"...\n"; |
| 167 | + }else { |
| 168 | +throwstd::runtime_error("Unsupported HTTP version number."); |
124 | 169 | } |
125 | 170 |
|
126 | | -if (error != boost::asio::error::eof) |
127 | | -throwboost::system::system_error(error); |
128 | | - |
129 | 171 | response_ <<body(body_stream.str()); |
130 | 172 | } |
131 | 173 |
|
|