@@ -99,74 +99,87 @@ namespace boost { namespace network { namespace http { namespace impl {
9999 }
100100
101101template <class Socket >
102- void read_body (Socket & socket_, basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
103- typename ostringstream<Tag>::type body_stream;
104-
102+ void read_body_normal (Socket & socket_, basic_response<Tag> & response_, boost::asio::streambuf & response_buffer,typename ostringstream<Tag>::type & body_stream) {
105103 boost::system::error_code error;
106- // TODO tag dispatch based on whether it's HTTP 1.0 or HTTP 1.1
107- if (version_major ==1 && version_minor ==0 ) {
108- if (response_buffer.size () >0 )
109- body_stream << &response_buffer;
104+ if (response_buffer.size () >0 )
105+ body_stream << &response_buffer;
110106
111- while (boost::asio::read (socket_, response_buffer,boost::asio::transfer_at_least (1 ), error)) {
107+ while (boost::asio::read (socket_, response_buffer,boost::asio::transfer_at_least (1 ), error)) {
108+ body_stream << &response_buffer;
109+ }
110+ }
111+
112+ template <class Socket >
113+ void read_body_transfer_chunk_encoding (Socket & socket_, basic_response<Tag> & response_, boost::asio::streambuf & response_buffer,typename ostringstream<Tag>::type & body_stream) {
114+ boost::system::error_code error;
115+ // look for the content-length header
116+ typename headers_range<basic_response<Tag> >::type content_length_range =
117+ headers (response_)[" Content-Length" ];
118+ if (empty (content_length_range)) {
119+ typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
120+ headers (response_)[" Transfer-Encoding" ];
121+ if (empty (transfer_encoding_range))throw std::runtime_error (" Missing Transfer-Encoding Header from response." );
122+ if (boost::iequals (begin (transfer_encoding_range)->second ," chunked" )) {
123+ bool stopping =false ;
124+ do {
125+ std::size_t chunk_size_line =read_until (socket_, response_buffer," \r\n " , error);
126+ if ((chunk_size_line ==0 ) && (error != boost::asio::error::eof))throw boost::system::system_error (error);
127+ std::size_t chunk_size =0 ;
128+ string_type data;
129+ {
130+ std::istreamchunk_stream (&response_buffer);
131+ std::getline (chunk_stream, data);
132+ typename istringstream<Tag>::typechunk_size_stream (data);
133+ chunk_size_stream >> std::hex >> chunk_size;
134+ }
135+ if (chunk_size ==0 ) {
136+ stopping =true ;
137+ if (!read_until (socket_, response_buffer," \r\n " , error) && (error != boost::asio::error::eof))
138+ throw boost::system::system_error (error);
139+ }else {
140+ bool stopping_inner =false ;
141+ do {
142+ std::size_t chunk_bytes_read =read (socket_, response_buffer,boost::asio::transfer_at_least (chunk_size +2 ), error);
143+ if (chunk_bytes_read ==0 ) {
144+ if (error != boost::asio::error::eof)throw boost::system::system_error (error);
145+ stopping_inner =true ;
146+ }
147+
148+ std::istreambuf_iterator<char > eos;
149+ std::istreambuf_iterator<char >stream_iterator (&response_buffer);
150+ for (; chunk_size >0 && stream_iterator != eos; --chunk_size)
151+ body_stream << *stream_iterator++;
152+ response_buffer.consume (2 );
153+ }while (!stopping_inner && chunk_size !=0 );
154+
155+ if (chunk_size !=0 )
156+ throw std::runtime_error (" Size mismatch between tranfer encoding chunk data size and declared chunk size." );
157+ }
158+ }while (!stopping);
159+ }else throw std::runtime_error (" Unsupported Transfer-Encoding." );
160+ }else {
161+ size_t length = lexical_cast<size_t >(begin (content_length_range)->second );
162+ size_t bytes_read =0 ;
163+ while ((bytes_read =boost::asio::read (socket_, response_buffer,boost::asio::transfer_at_least (1 ), error))) {
112164 body_stream << &response_buffer;
165+ length -= bytes_read;
166+ if ((length <=0 )or error)
167+ break ;
113168 }
169+ }
170+ }
171+
172+ template <class Socket >
173+ void read_body (Socket & socket_, basic_response<Tag> & response_, boost::asio::streambuf & response_buffer) {
174+ typename ostringstream<Tag>::type body_stream;
175+ // TODO tag dispatch based on whether it's HTTP 1.0 or HTTP 1.1
176+ if (version_major ==1 && version_minor ==0 ) {
177+ read_body_normal (socket_, response_, response_buffer, body_stream);
114178 }else if (version_major ==1 && version_minor ==1 ) {
115- // look for the content-length header
116- typename headers_range<basic_response<Tag> >::type content_length_range =
117- headers (response_)[" Content-Length" ];
118- if (empty (content_length_range)) {
119- typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
120- headers (response_)[" Transfer-Encoding" ];
121- if (empty (transfer_encoding_range))throw std::runtime_error (" Missing Transfer-Encoding Header from response." );
122- if (boost::iequals (begin (transfer_encoding_range)->second ," chunked" )) {
123- bool stopping =false ;
124- do {
125- std::size_t chunk_size_line =read_until (socket_, response_buffer," \r\n " , error);
126- if ((chunk_size_line ==0 ) && (error != boost::asio::error::eof))throw boost::system::system_error (error);
127- std::size_t chunk_size =0 ;
128- string_type data;
129- {
130- std::istreamchunk_stream (&response_buffer);
131- std::getline (chunk_stream, data);
132- typename istringstream<Tag>::typechunk_size_stream (data);
133- chunk_size_stream >> std::hex >> chunk_size;
134- }
135- if (chunk_size ==0 ) {
136- stopping =true ;
137- if (!read_until (socket_, response_buffer," \r\n " , error) && (error != boost::asio::error::eof))
138- throw boost::system::system_error (error);
139- }else {
140- bool stopping_inner =false ;
141- do {
142- std::size_t chunk_bytes_read =read (socket_, response_buffer,boost::asio::transfer_at_least (chunk_size +2 ), error);
143- if (chunk_bytes_read ==0 ) {
144- if (error != boost::asio::error::eof)throw boost::system::system_error (error);
145- stopping_inner =true ;
146- }
147-
148- std::istreambuf_iterator<char > eos;
149- std::istreambuf_iterator<char >stream_iterator (&response_buffer);
150- for (; chunk_size >0 && stream_iterator != eos; --chunk_size)
151- body_stream << *stream_iterator++;
152- response_buffer.consume (2 );
153- }while (!stopping_inner && chunk_size !=0 );
154-
155- if (chunk_size !=0 )
156- throw std::runtime_error (" Size mismatch between tranfer encoding chunk data size and declared chunk size." );
157- }
158- }while (!stopping);
159- }else throw std::runtime_error (" Unsupported Transfer-Encoding." );
160- }else {
161- size_t length = lexical_cast<size_t >(begin (content_length_range)->second );
162- size_t bytes_read =0 ;
163- while ((bytes_read =boost::asio::read (socket_, response_buffer,boost::asio::transfer_at_least (1 ), error))) {
164- body_stream << &response_buffer;
165- length -= bytes_read;
166- if ((length <=0 )or error)
167- break ;
168- }
169- }
179+ if (response_.version () ==" HTTP/1.0" )
180+ read_body_normal (socket_, response_, response_buffer, body_stream);
181+ else
182+ read_body_transfer_chunk_encoding (socket_, response_, response_buffer, body_stream);
170183 }else {
171184throw std::runtime_error (" Unsupported HTTP version number." );
172185 }