Skip to content

Commit 1277fa6

Browse files
authored
Merge pull request cpp-netlib#719 from chenzhaoyu/add-active-client-side-close-0.13-release
add client side close for 0.13-release
2 parents c138247 + 0e91891 commit 1277fa6

File tree

1 file changed

+66
-2
lines changed

1 file changed

+66
-2
lines changed

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

+66-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,16 @@ struct http_async_protocol_handler {
266270
}
267271
trim(header_pair.second);
268272
headers.insert(header_pair);
273+
if (!is_content_length &&
274+
boost::iequals(header_pair.first, "Content-Length")) {
275+
try {
276+
content_length = std::stoll(header_pair.second);
277+
is_content_length = true;
278+
}
279+
catch (std::exception&) {
280+
//is_content_length = false;
281+
}
282+
}
269283
}
270284
// determine if the body parser will need to handle chunked encoding
271285
typename headers_range<basic_response<Tag> >::type transfer_encoding_range =
@@ -325,6 +339,49 @@ struct http_async_protocol_handler {
325339
parsed_ok, std::distance(std::end(result_range), part_end));
326340
}
327341

342+
inline bool check_parse_body_complete() const {
343+
if (this->is_chunk_encoding) {
344+
return parse_chunk_encoding_complete();
345+
}
346+
if (this->is_content_length && this->content_length >= 0) {
347+
return parse_content_length_complete();
348+
}
349+
return false;
350+
}
351+
352+
inline bool parse_content_length_complete() const {
353+
return this->partial_parsed.length() >= this-> content_length;
354+
}
355+
356+
bool parse_chunk_encoding_complete() const {
357+
string_type body;
358+
string_type crlf = "\r\n";
359+
360+
typename string_type::const_iterator begin = partial_parsed.begin();
361+
for (typename string_type::const_iterator iter =
362+
std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end());
363+
iter != partial_parsed.end();
364+
iter =
365+
std::search(begin, partial_parsed.end(), crlf.begin(), crlf.end())) {
366+
string_type line(begin, iter);
367+
if (line.empty()) {
368+
std::advance(iter, 2);
369+
begin = iter;
370+
continue;
371+
}
372+
std::stringstream stream(line);
373+
int len;
374+
stream >> std::hex >> len;
375+
std::advance(iter, 2);
376+
if (!len) return true;
377+
if (len <= partial_parsed.end() - iter) {
378+
std::advance(iter, len + 2);
379+
}
380+
begin = iter;
381+
}
382+
return false;
383+
}
384+
328385
template <class Delegate, class Callback>
329386
void parse_body(Delegate& delegate_, Callback callback, size_t bytes) {
330387
// TODO(dberris): we should really not use a string for the partial body
@@ -333,8 +390,12 @@ struct http_async_protocol_handler {
333390
std::advance(it, bytes);
334391
partial_parsed.append(part_begin, it);
335392
part_begin = part.begin();
336-
delegate_->read_some(
337-
boost::asio::mutable_buffers_1(part.data(), part.size()), callback);
393+
if (check_parse_body_complete()) {
394+
callback(boost::asio::error::eof, bytes);
395+
} else {
396+
delegate_->read_some(
397+
boost::asio::mutable_buffers_1(part.data(), part.size()), callback);
398+
}
338399
}
339400

340401
typedef response_parser<Tag> response_parser_type;
@@ -353,6 +414,9 @@ struct http_async_protocol_handler {
353414
typename buffer_type::const_iterator part_begin;
354415
string_type partial_parsed;
355416
bool is_chunk_encoding;
417+
bool is_chunk_end;
418+
bool is_content_length;
419+
long long content_length;
356420
};
357421

358422
} // namespace impl

0 commit comments

Comments
 (0)