support out buf when request (#450)
This commit is contained in:
parent
b9d6008481
commit
72253d30e7
|
@ -31,6 +31,7 @@ using coro_http_client = cinatra::coro_http_client;
|
||||||
using req_content_type = cinatra::req_content_type;
|
using req_content_type = cinatra::req_content_type;
|
||||||
using resp_data = cinatra::resp_data;
|
using resp_data = cinatra::resp_data;
|
||||||
using http_method = cinatra::http_method;
|
using http_method = cinatra::http_method;
|
||||||
template <typename String>
|
using http_header = cinatra::http_header;
|
||||||
|
template <typename String = std::string>
|
||||||
using req_context = cinatra::req_context<String>;
|
using req_context = cinatra::req_context<String>;
|
||||||
} // namespace coro_http
|
} // namespace coro_http
|
|
@ -7,6 +7,7 @@
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <span>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -825,17 +826,25 @@ class coro_http_client {
|
||||||
template <typename S, typename String>
|
template <typename S, typename String>
|
||||||
async_simple::coro::Lazy<resp_data> async_request(
|
async_simple::coro::Lazy<resp_data> async_request(
|
||||||
S uri, http_method method, req_context<String> ctx,
|
S uri, http_method method, req_context<String> ctx,
|
||||||
std::unordered_map<std::string, std::string> headers = {}) {
|
std::unordered_map<std::string, std::string> headers = {},
|
||||||
|
std::span<char> out_buf = {}) {
|
||||||
if (!resp_chunk_str_.empty()) {
|
if (!resp_chunk_str_.empty()) {
|
||||||
resp_chunk_str_.clear();
|
resp_chunk_str_.clear();
|
||||||
}
|
}
|
||||||
if (!body_.empty()) {
|
if (!body_.empty()) {
|
||||||
body_.clear();
|
body_.clear();
|
||||||
}
|
}
|
||||||
|
if (!out_buf.empty()) {
|
||||||
|
out_buf_ = out_buf;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<int> guard(nullptr, [this](auto) {
|
std::shared_ptr<int> guard(nullptr, [this](auto) {
|
||||||
if (!req_headers_.empty()) {
|
if (!req_headers_.empty()) {
|
||||||
req_headers_.clear();
|
req_headers_.clear();
|
||||||
}
|
}
|
||||||
|
if (!out_buf_.empty()) {
|
||||||
|
out_buf_ = {};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
resp_data data{};
|
resp_data data{};
|
||||||
|
@ -1220,13 +1229,27 @@ class coro_http_client {
|
||||||
total_len_ = parser_.total_len();
|
total_len_ = parser_.total_len();
|
||||||
#endif
|
#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.
|
// Now get entire content, additional data will discard.
|
||||||
// copy body.
|
// copy body.
|
||||||
if (content_len > 0) {
|
if (content_len > 0) {
|
||||||
detail::resize(body_, content_len);
|
|
||||||
auto data_ptr = asio::buffer_cast<const char *>(read_buf_.data());
|
auto data_ptr = asio::buffer_cast<const char *>(read_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);
|
memcpy(body_.data(), data_ptr, content_len);
|
||||||
|
}
|
||||||
read_buf_.consume(read_buf_.size());
|
read_buf_.consume(read_buf_.size());
|
||||||
}
|
}
|
||||||
co_await handle_entire_content(data, content_len, is_ranges, ctx);
|
co_await handle_entire_content(data, content_len, is_ranges, ctx);
|
||||||
|
@ -1237,17 +1260,33 @@ class coro_http_client {
|
||||||
size_t part_size = read_buf_.size();
|
size_t part_size = read_buf_.size();
|
||||||
size_t size_to_read = content_len - part_size;
|
size_t size_to_read = content_len - part_size;
|
||||||
|
|
||||||
detail::resize(body_, content_len);
|
|
||||||
auto data_ptr = asio::buffer_cast<const char *>(read_buf_.data());
|
auto data_ptr = asio::buffer_cast<const char *>(read_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);
|
memcpy(body_.data(), data_ptr, part_size);
|
||||||
|
}
|
||||||
|
|
||||||
read_buf_.consume(part_size);
|
read_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(
|
if (std::tie(ec, size) = co_await async_read(
|
||||||
asio::buffer(body_.data() + part_size, size_to_read),
|
asio::buffer(body_.data() + part_size, size_to_read),
|
||||||
size_to_read);
|
size_to_read);
|
||||||
ec) {
|
ec) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now get entire content, additional data will discard.
|
// Now get entire content, additional data will discard.
|
||||||
co_await handle_entire_content(data, content_len, is_ranges, ctx);
|
co_await handle_entire_content(data, content_len, is_ranges, ctx);
|
||||||
|
@ -1268,8 +1307,13 @@ class coro_http_client {
|
||||||
if (content_len > 0) {
|
if (content_len > 0) {
|
||||||
const char *data_ptr;
|
const char *data_ptr;
|
||||||
if (read_buf_.size() == 0) {
|
if (read_buf_.size() == 0) {
|
||||||
|
if (out_buf_.empty()) {
|
||||||
data_ptr = body_.data();
|
data_ptr = body_.data();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
data_ptr = out_buf_.data();
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
data_ptr = asio::buffer_cast<const char *>(read_buf_.data());
|
data_ptr = asio::buffer_cast<const char *>(read_buf_.data());
|
||||||
}
|
}
|
||||||
|
@ -1698,6 +1742,7 @@ class coro_http_client {
|
||||||
std::chrono::seconds(60);
|
std::chrono::seconds(60);
|
||||||
bool enable_tcp_no_delay_ = false;
|
bool enable_tcp_no_delay_ = false;
|
||||||
std::string resp_chunk_str_;
|
std::string resp_chunk_str_;
|
||||||
|
std::span<char> out_buf_;
|
||||||
|
|
||||||
#ifdef BENCHMARK_TEST
|
#ifdef BENCHMARK_TEST
|
||||||
std::string req_str_;
|
std::string req_str_;
|
||||||
|
|
|
@ -141,8 +141,26 @@ async_simple::coro::Lazy<void> ranges_download_files(
|
||||||
std::cout << result.status << "\n";
|
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<char>{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() {
|
int main() {
|
||||||
test_sync_client();
|
test_sync_client();
|
||||||
|
use_out_buf();
|
||||||
|
|
||||||
coro_http::coro_http_client client{};
|
coro_http::coro_http_client client{};
|
||||||
async_simple::coro::syncAwait(test_async_client(client));
|
async_simple::coro::syncAwait(test_async_client(client));
|
||||||
|
|
Loading…
Reference in New Issue