in include/ylt/standalone/cinatra/coro_http_client.hpp [1677:1824]
async_simple::coro::Lazy<resp_data> handle_read(std::error_code &ec,
size_t &size,
bool &is_keep_alive,
req_context<String> ctx,
http_method method) {
resp_data data{};
do {
if (std::tie(ec, size) = co_await async_read_until(head_buf_, TWO_CRCF);
ec) {
break;
}
ec = handle_header(data, parser_, size);
if (ec) {
break;
}
is_keep_alive = parser_.keep_alive();
if (method == http_method::HEAD) {
co_return data;
}
bool is_out_buf = false;
bool is_ranges = parser_.is_resp_ranges();
if (is_ranges) {
is_keep_alive = true;
}
if (parser_.is_chunked()) {
out_buf_ = {};
is_keep_alive = true;
if (head_buf_.size() > 0) {
const char *data_ptr =
asio::buffer_cast<const char *>(head_buf_.data());
chunked_buf_.sputn(data_ptr, head_buf_.size());
head_buf_.consume(head_buf_.size());
}
ec = co_await handle_chunked(data, std::move(ctx));
break;
}
if (parser_.is_multipart()) {
out_buf_ = {};
is_keep_alive = true;
if (head_buf_.size() > 0) {
const char *data_ptr =
asio::buffer_cast<const char *>(head_buf_.data());
chunked_buf_.sputn(data_ptr, head_buf_.size());
head_buf_.consume(head_buf_.size());
}
ec = co_await handle_multipart(data, std::move(ctx));
break;
}
redirect_uri_.clear();
bool is_redirect = parser_.is_location();
if (is_redirect)
redirect_uri_ = parser_.get_header_value("Location");
if (!parser_.get_header_value("Content-Encoding").empty()) {
if (parser_.get_header_value("Content-Encoding").find("gzip") !=
std::string_view::npos)
encoding_type_ = content_encoding::gzip;
else if (parser_.get_header_value("Content-Encoding").find("deflate") !=
std::string_view::npos)
encoding_type_ = content_encoding::deflate;
else if (parser_.get_header_value("Content-Encoding").find("br") !=
std::string_view::npos)
encoding_type_ = content_encoding::br;
}
else {
encoding_type_ = content_encoding::none;
}
size_t content_len = (size_t)parser_.body_len();
#ifdef BENCHMARK_TEST
total_len_ = parser_.total_len();
#endif
is_out_buf = !out_buf_.empty();
if (is_out_buf) {
if (content_len > 0 && out_buf_.size() < content_len) {
out_buf_ = {};
is_out_buf = false;
}
}
if (content_len <= head_buf_.size()) {
// Now get entire content, additional data will discard.
// copy body.
if (content_len > 0) {
auto data_ptr = asio::buffer_cast<const char *>(head_buf_.data());
if (is_out_buf) {
memcpy(out_buf_.data(), data_ptr, content_len);
}
else {
detail::resize(body_, content_len);
memcpy(body_.data(), data_ptr, content_len);
}
head_buf_.consume(head_buf_.size());
}
co_await handle_entire_content(data, content_len, is_ranges, ctx);
break;
}
// read left part of content.
size_t part_size = head_buf_.size();
size_t size_to_read = content_len - part_size;
auto data_ptr = asio::buffer_cast<const char *>(head_buf_.data());
if (is_out_buf) {
memcpy(out_buf_.data(), data_ptr, part_size);
}
else {
detail::resize(body_, content_len);
memcpy(body_.data(), data_ptr, part_size);
}
head_buf_.consume(part_size);
if (is_out_buf) {
if (std::tie(ec, size) = co_await async_read(
asio::buffer(out_buf_.data() + part_size, size_to_read),
size_to_read);
ec) {
break;
}
}
else {
if (std::tie(ec, size) = co_await async_read(
asio::buffer(body_.data() + part_size, size_to_read),
size_to_read);
ec) {
break;
}
}
// Now get entire content, additional data will discard.
co_await handle_entire_content(data, content_len, is_ranges, ctx);
} while (0);
if (!resp_chunk_str_.empty()) {
data.resp_body =
std::string_view{resp_chunk_str_.data(), resp_chunk_str_.size()};
}
co_return data;
}