Skip to content

Commit 3183577

Browse files
authored
Merge pull request cpp-netlib#713 from chenzhaoyu/add-active-client-side-close
add client size close for cpp-netlib#712
2 parents 8554867 + b950ea5 commit 3183577

File tree

1 file changed

+60
-2
lines changed

1 file changed

+60
-2
lines changed

boost/network/protocol/http/client/connection/async_protocol_handler.hpp

+60-2
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,10 @@ struct http_async_protocol_handler {
246246
response_parser_type::http_header_line_done);
247247
typename headers_container<Tag>::type headers;
248248
std::pair<string_type, string_type> header_pair;
249+
//init params
250+
is_content_length = false;
251+
content_length = -1;
252+
is_chunk_end = false;
249253
while (!boost::empty(input_range)) {
250254
std::tie(parsed_ok, result_range) = headers_parser.parse_until(
251255
response_parser_type::http_header_colon, input_range);
@@ -266,6 +270,10 @@ struct http_async_protocol_handler {
266270
}
267271
trim(header_pair.second);
268272
headers.insert(header_pair);
273+
if (boost::iequals(header_pair.first, "Content-Length")) {
274+
is_content_length = true;
275+
content_length = std::stoi(header_pair.second);
276+
}
269277
}
270278
// determine if the body parser will need to handle chunked encoding
271279
typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
@@ -325,14 +333,61 @@ struct http_async_protocol_handler {
325333
parsed_ok, std::distance(std::end(result_range), part_end));
326334
}
327335

336+
inline bool check_parse_body_complete() const {
337+
if (this->is_chunk_encoding) {
338+
return parse_chunk_encoding_complete();
339+
}
340+
if (this->is_content_length && this->content_length >= 0) {
341+
return parse_content_length_complete();
342+
}
343+
return false;
344+
}
345+
346+
inline bool parse_content_length_complete() const {
347+
return this->partial_parsed.length() >= this-> content_length;
348+
}
349+
350+
bool parse_chunk_encoding_complete() const {
351+
string_type body;
352+
string_type crlf = "\r\n";
353+
354+
typename string_type::const_iterator begin = partial_parsed.begin();
355+
for (typename string_type::const_iterator iter =
356+
std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end());
357+
iter != partial_parsed.end();
358+
iter =
359+
std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end())) {
360+
string_type line(begin, iter);
361+
if (line.empty()) {
362+
std::advance(iter, 2);
363+
begin = iter;
364+
continue;
365+
}
366+
std::stringstream stream(line);
367+
int len;
368+
stream >> std::hex >> len;
369+
std::advance(iter, 2);
370+
if (!len) return true;
371+
if (len <= partial_parsed.end() - iter) {
372+
std::advance(iter, len + 2);
373+
}
374+
begin = iter;
375+
}
376+
return false;
377+
}
378+
328379
template <class Delegate, class Callback>
329380
void parse_body(Delegate& delegate_, Callback callback, size_t bytes) {
330381
// TODO(dberris): we should really not use a string for the partial body
331382
// buffer.
332383
partial_parsed.append(part_begin, part_begin + bytes);
333384
part_begin = part.begin();
334-
delegate_->read_some(
335-
boost::asio::mutable_buffers_1(part.data(), part.size()), callback);
385+
if (check_parse_body_complete()) {
386+
callback(boost::asio::error::eof, bytes);
387+
} else {
388+
delegate_->read_some(
389+
boost::asio::mutable_buffers_1(part.data(), part.size()), callback);
390+
}
336391
}
337392

338393
typedef response_parser<Tag> response_parser_type;
@@ -351,6 +406,9 @@ struct http_async_protocol_handler {
351406
typename buffer_type::const_iterator part_begin;
352407
string_type partial_parsed;
353408
bool is_chunk_encoding;
409+
bool is_chunk_end;
410+
bool is_content_length;
411+
std::size_t content_length;
354412
};
355413

356414
} // namespace impl

0 commit comments

Comments
 (0)