From ba244fb36b5eda004b44aed3c9d5146d918a87ad Mon Sep 17 00:00:00 2001 From: qicosmos Date: Tue, 12 Sep 2023 10:18:52 +0800 Subject: [PATCH] support out buf when request --- include/ylt/coro_http/coro_http_client.hpp | 3 +- .../thirdparty/cinatra/coro_http_client.hpp | 69 +++++++++++++++---- src/coro_http/examples/example.cpp | 18 +++++ 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/include/ylt/coro_http/coro_http_client.hpp b/include/ylt/coro_http/coro_http_client.hpp index 706797b2e..ac33ce3c8 100644 --- a/include/ylt/coro_http/coro_http_client.hpp +++ b/include/ylt/coro_http/coro_http_client.hpp @@ -31,6 +31,7 @@ using coro_http_client = cinatra::coro_http_client; using req_content_type = cinatra::req_content_type; using resp_data = cinatra::resp_data; using http_method = cinatra::http_method; -template +using http_header = cinatra::http_header; +template using req_context = cinatra::req_context; } // namespace coro_http \ No newline at end of file diff --git a/include/ylt/thirdparty/cinatra/coro_http_client.hpp b/include/ylt/thirdparty/cinatra/coro_http_client.hpp index 66aec59f7..393f54d07 100644 --- a/include/ylt/thirdparty/cinatra/coro_http_client.hpp +++ b/include/ylt/thirdparty/cinatra/coro_http_client.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -825,17 +826,25 @@ class coro_http_client { template async_simple::coro::Lazy async_request( S uri, http_method method, req_context ctx, - std::unordered_map headers = {}) { + std::unordered_map headers = {}, + std::span out_buf = {}) { if (!resp_chunk_str_.empty()) { resp_chunk_str_.clear(); } if (!body_.empty()) { body_.clear(); } + if (!out_buf.empty()) { + out_buf_ = out_buf; + } + std::shared_ptr guard(nullptr, [this](auto) { if (!req_headers_.empty()) { req_headers_.clear(); } + if (!out_buf_.empty()) { + out_buf_ = {}; + } }); resp_data data{}; @@ -1220,13 +1229,27 @@ class coro_http_client { total_len_ = parser_.total_len(); #endif - if ((size_t)parser_.body_len() <= read_buf_.size()) { + bool is_out_buf = !out_buf_.empty(); + if (is_out_buf) { + if (content_len > 0 && out_buf_.size() < content_len) { + data.status = 404; + data.net_err = std::make_error_code(std::errc::no_buffer_space); + co_return data; + } + } + + if (content_len <= read_buf_.size()) { // Now get entire content, additional data will discard. // copy body. if (content_len > 0) { - detail::resize(body_, content_len); auto data_ptr = asio::buffer_cast(read_buf_.data()); - memcpy(body_.data(), data_ptr, content_len); + 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); + } read_buf_.consume(read_buf_.size()); } co_await handle_entire_content(data, content_len, is_ranges, ctx); @@ -1237,16 +1260,32 @@ class coro_http_client { size_t part_size = read_buf_.size(); size_t size_to_read = content_len - part_size; - detail::resize(body_, content_len); auto data_ptr = asio::buffer_cast(read_buf_.data()); - memcpy(body_.data(), data_ptr, part_size); + 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); + } + read_buf_.consume(part_size); - if (std::tie(ec, size) = co_await async_read( - asio::buffer(body_.data() + part_size, size_to_read), - size_to_read); - ec) { - break; + 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. @@ -1268,7 +1307,12 @@ class coro_http_client { if (content_len > 0) { const char *data_ptr; if (read_buf_.size() == 0) { - data_ptr = body_.data(); + if (out_buf_.empty()) { + data_ptr = body_.data(); + } + else { + data_ptr = out_buf_.data(); + } } else { data_ptr = asio::buffer_cast(read_buf_.data()); @@ -1698,6 +1742,7 @@ class coro_http_client { std::chrono::seconds(60); bool enable_tcp_no_delay_ = false; std::string resp_chunk_str_; + std::span out_buf_; #ifdef BENCHMARK_TEST std::string req_str_; diff --git a/src/coro_http/examples/example.cpp b/src/coro_http/examples/example.cpp index 07185d0f6..429a7e5a8 100644 --- a/src/coro_http/examples/example.cpp +++ b/src/coro_http/examples/example.cpp @@ -141,8 +141,26 @@ async_simple::coro::Lazy ranges_download_files( std::cout << result.status << "\n"; } +void use_out_buf() { + using namespace coro_http; + std::string str; + str.resize(10); + std::string url = "http://cn.bing.com"; + + str.resize(6400); + coro_http_client client; + auto ret = client.async_request(url, http_method::GET, req_context<>{}, {}, + std::span{str.data(), str.size()}); + auto result = async_simple::coro::syncAwait(ret); + bool ok = result.status == 200 || result.status == 301; + assert(ok); + std::string_view sv(str.data(), result.resp_body.size()); + assert(result.resp_body == sv); +} + int main() { test_sync_client(); + use_out_buf(); coro_http::coro_http_client client{}; async_simple::coro::syncAwait(test_async_client(client));