From 411a5427bde62e9ee89d44f3f9d380c02f346e76 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Mon, 25 Dec 2023 14:21:37 +0800 Subject: [PATCH 1/2] set sni host name as default --- .../thirdparty/cinatra/coro_http_client.hpp | 45 ++++++++++--------- src/coro_http/examples/example.cpp | 13 +++--- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/include/ylt/thirdparty/cinatra/coro_http_client.hpp b/include/ylt/thirdparty/cinatra/coro_http_client.hpp index b4fc9ea20..b250c24dc 100644 --- a/include/ylt/thirdparty/cinatra/coro_http_client.hpp +++ b/include/ylt/thirdparty/cinatra/coro_http_client.hpp @@ -181,8 +181,8 @@ class coro_http_client : public std::enable_shared_from_this { } #ifdef CINATRA_ENABLE_SSL if (conf.use_ssl) { - return init_ssl(conf.base_path, conf.cert_file, conf.verify_mode, - conf.domain); + return init_ssl(conf.domain, conf.base_path, conf.cert_file, + conf.verify_mode); } return true; #endif @@ -201,9 +201,9 @@ class coro_http_client : public std::enable_shared_from_this { } #ifdef CINATRA_ENABLE_SSL - bool init_ssl(const std::string &base_path, const std::string &cert_file, - int verify_mode = asio::ssl::verify_none, - const std::string &domain = "localhost") { + bool init_ssl(const std::string &sni_hostname, const std::string &base_path, + const std::string &cert_file, + int verify_mode = asio::ssl::verify_none) { try { ssl_init_ret_ = false; ssl_ctx_ = @@ -223,19 +223,22 @@ class coro_http_client : public std::enable_shared_from_this { ssl_ctx_->set_verify_mode(verify_mode); - // ssl_ctx_.add_certificate_authority(asio::buffer(CA_PEM)); - if (!domain.empty()) - ssl_ctx_->set_verify_callback( - asio::ssl::host_name_verification(domain)); - socket_->ssl_stream_ = std::make_unique>( socket_->impl_, *ssl_ctx_); - // Set SNI Hostname (many hosts need this to handshake successfully) - if (!sni_hostname_.empty()) { - SSL_set_tlsext_host_name(socket_->ssl_stream_->native_handle(), - sni_hostname_.c_str()); + + // ssl_ctx_.add_certificate_authority(asio::buffer(CA_PEM)); + if (!sni_hostname.empty()) { + ssl_ctx_->set_verify_callback( + asio::ssl::host_name_verification(sni_hostname)); + + if (need_set_sni_host_) { + // Set SNI Hostname (many hosts need this to handshake successfully) + SSL_set_tlsext_host_name(socket_->ssl_stream_->native_handle(), + sni_hostname.c_str()); + } } + use_ssl_ = true; ssl_init_ret_ = true; } catch (std::exception &e) { @@ -244,9 +247,9 @@ class coro_http_client : public std::enable_shared_from_this { return ssl_init_ret_; } - [[nodiscard]] bool init_ssl(std::string full_path = "", - int verify_mode = asio::ssl::verify_none, - const std::string &domain = "localhost") { + [[nodiscard]] bool init_ssl(const std::string &sni_hostname = "", + std::string full_path = "", + int verify_mode = asio::ssl::verify_none) { std::string base_path; std::string cert_file; if (full_path.empty()) { @@ -257,7 +260,7 @@ class coro_http_client : public std::enable_shared_from_this { base_path = full_path.substr(0, full_path.find_last_of('/')); cert_file = full_path.substr(full_path.find_last_of('/') + 1); } - return init_ssl(base_path, cert_file, verify_mode, domain); + return init_ssl(sni_hostname, base_path, cert_file, verify_mode); } #endif @@ -797,7 +800,7 @@ class coro_http_client : public std::enable_shared_from_this { socket_->has_closed_ = true; #ifdef CINATRA_ENABLE_SSL - sni_hostname_ = ""; + need_set_sni_host_ = true; if (use_ssl_) { socket_->ssl_stream_ = nullptr; socket_->ssl_stream_ = @@ -1128,7 +1131,7 @@ class coro_http_client : public std::enable_shared_from_this { } #ifdef CINATRA_ENABLE_SSL - void set_sni_hostname(const std::string &host) { sni_hostname_ = host; } + void enable_sni_hostname(bool r) { need_set_sni_host_ = r; } #endif template @@ -1869,7 +1872,7 @@ class coro_http_client : public std::enable_shared_from_this { std::unique_ptr ssl_ctx_ = nullptr; bool ssl_init_ret_ = true; bool use_ssl_ = false; - std::string sni_hostname_ = ""; + bool need_set_sni_host_ = true; #endif std::string redirect_uri_; bool enable_follow_redirect_ = false; diff --git a/src/coro_http/examples/example.cpp b/src/coro_http/examples/example.cpp index 6b5fc0dce..37829003a 100644 --- a/src/coro_http/examples/example.cpp +++ b/src/coro_http/examples/example.cpp @@ -76,13 +76,10 @@ async_simple::coro::Lazy test_async_client( async_simple::coro::Lazy test_async_ssl_client( coro_http::coro_http_client &client) { #ifdef CINATRA_ENABLE_SSL - std::string uri2 = "https://www.baidu.com"; - std::string uri3 = "https://cn.bing.com"; - [[maybe_unused]] auto ec = - client.init_ssl("../../include/cinatra", "server.crt"); - auto data = co_await client.async_get(uri2); - std::cout << data.status << std::endl; - data = co_await client.async_get(uri3); + std::string uri = "https://cn.bing.com"; + [[maybe_unused]] auto ec = client.init_ssl("cn.bing.com"); + auto data = co_await client.async_get(uri); + std::cout << data.net_err.message() << "\n"; std::cout << data.status << std::endl; #endif co_return; @@ -227,7 +224,7 @@ void test_coro_http_server() { int main() { test_coro_http_server(); test_sync_client(); - use_out_buf(); + // use_out_buf(); coro_http::coro_http_client client{}; async_simple::coro::syncAwait(test_async_client(client)); From fe1c11da0ca010bfdb51b13d7f4c8dd8b565c85e Mon Sep 17 00:00:00 2001 From: qicosmos Date: Wed, 3 Jan 2024 11:34:27 +0800 Subject: [PATCH 2/2] improve and add more examples --- .../thirdparty/cinatra/coro_http_client.hpp | 150 ++++++++--- src/coro_http/examples/example.cpp | 238 ++++++++++++++++-- 2 files changed, 327 insertions(+), 61 deletions(-) diff --git a/include/ylt/thirdparty/cinatra/coro_http_client.hpp b/include/ylt/thirdparty/cinatra/coro_http_client.hpp index 0d6af95f8..cd43ca035 100644 --- a/include/ylt/thirdparty/cinatra/coro_http_client.hpp +++ b/include/ylt/thirdparty/cinatra/coro_http_client.hpp @@ -180,11 +180,7 @@ class coro_http_client : public std::enable_shared_from_this { enable_tcp_no_delay_ = conf.enable_tcp_no_delay; } #ifdef CINATRA_ENABLE_SSL - if (conf.use_ssl) { - return init_ssl(conf.domain, conf.base_path, conf.cert_file, - conf.verify_mode); - } - return true; + set_ssl_schema(conf.use_ssl); #endif return true; } @@ -201,11 +197,13 @@ class coro_http_client : public std::enable_shared_from_this { } #ifdef CINATRA_ENABLE_SSL - bool init_ssl(const std::string &sni_hostname, const std::string &base_path, - const std::string &cert_file, - int verify_mode = asio::ssl::verify_none) { + bool init_ssl(int verify_mode, const std::string &base_path, + const std::string &cert_file, const std::string &sni_hostname) { + if (has_init_ssl_) { + return true; + } + try { - ssl_init_ret_ = false; ssl_ctx_ = std::make_unique(asio::ssl::context::sslv23); auto full_cert_file = std::filesystem::path(base_path).append(cert_file); @@ -239,17 +237,17 @@ class coro_http_client : public std::enable_shared_from_this { } } - use_ssl_ = true; - ssl_init_ret_ = true; + has_init_ssl_ = true; } catch (std::exception &e) { CINATRA_LOG_ERROR << "init ssl failed: " << e.what(); + return false; } - return ssl_init_ret_; + return true; } - [[nodiscard]] bool init_ssl(const std::string &sni_hostname = "", + [[nodiscard]] bool init_ssl(int verify_mode = asio::ssl::verify_peer, std::string full_path = "", - int verify_mode = asio::ssl::verify_none) { + const std::string &sni_hostname = "") { std::string base_path; std::string cert_file; if (full_path.empty()) { @@ -260,7 +258,7 @@ class coro_http_client : public std::enable_shared_from_this { base_path = full_path.substr(0, full_path.find_last_of('/')); cert_file = full_path.substr(full_path.find_last_of('/') + 1); } - return init_ssl(sni_hostname, base_path, cert_file, verify_mode); + return init_ssl(verify_mode, base_path, cert_file, sni_hostname); } #endif @@ -801,7 +799,7 @@ class coro_http_client : public std::enable_shared_from_this { socket_->has_closed_ = true; #ifdef CINATRA_ENABLE_SSL need_set_sni_host_ = true; - if (use_ssl_) { + if (has_init_ssl_) { socket_->ssl_stream_ = nullptr; socket_->ssl_stream_ = std::make_unique>( @@ -993,7 +991,15 @@ class coro_http_client : public std::enable_shared_from_this { bool no_schema = !has_schema(uri); if (no_schema) { - append_uri.append("http://").append(uri); +#ifdef CINATRA_ENABLE_SSL + if (is_ssl_schema_) { + append_uri.append("https://").append(uri); + } + else +#endif + { + append_uri.append("http://").append(uri); + } } bool ok = false; std::tie(ok, u) = handle_uri(data, no_schema ? append_uri : uri); @@ -1022,6 +1028,23 @@ class coro_http_client : public std::enable_shared_from_this { } if (u.is_ssl) { +#ifdef CINATRA_ENABLE_SSL + if (!has_init_ssl_) { + size_t pos = u.host.find("www."); + std::string host; + if (pos != std::string_view::npos) { + host = std::string{u.host.substr(pos + 4)}; + } + else { + host = std::string{u.host}; + } + bool r = init_ssl(asio::ssl::verify_peer, "", host); + if (!r) { + data.net_err = std::make_error_code(std::errc::invalid_argument); + co_return data; + } + } +#endif if (ec = co_await handle_shake(); ec) { break; } @@ -1072,7 +1095,7 @@ class coro_http_client : public std::enable_shared_from_this { async_simple::coro::Lazy handle_shake() { #ifdef CINATRA_ENABLE_SSL - if (use_ssl_) { + if (has_init_ssl_) { if (socket_->ssl_stream_ == nullptr) { co_return std::make_error_code(std::errc::not_a_stream); } @@ -1112,6 +1135,10 @@ class coro_http_client : public std::enable_shared_from_this { enable_follow_redirect_ = enable_follow_redirect; } +#ifdef CINATRA_ENABLE_SSL + void set_ssl_schema(bool r) { is_ssl_schema_ = r; } +#endif + std::string get_redirect_uri() { return redirect_uri_; } bool is_redirect(resp_data &data) { @@ -1694,14 +1721,21 @@ class coro_http_client : public std::enable_shared_from_this { async_simple::coro::Lazy async_read_ws() { resp_data data{}; - auto self = this->shared_from_this(); read_buf_.consume(read_buf_.size()); size_t header_size = 2; std::shared_ptr sock = socket_; auto on_ws_msg = std::move(on_ws_msg_); + auto on_ws_close = std::move(on_ws_close_); + asio::streambuf &read_buf = sock->read_buf_; + bool has_init_ssl = false; +#ifdef CINATRA_ENABLE_SSL + has_init_ssl = has_init_ssl_; +#endif websocket ws{}; while (true) { - if (auto [ec, _] = co_await async_read(read_buf_, header_size); ec) { + if (auto [ec, _] = + co_await async_read_ws(sock, read_buf, header_size, has_init_ssl); + ec) { data.net_err = ec; data.status = 404; @@ -1716,7 +1750,7 @@ class coro_http_client : public std::enable_shared_from_this { co_return; } - const char *data_ptr = asio::buffer_cast(read_buf_.data()); + const char *data_ptr = asio::buffer_cast(read_buf.data()); auto ret = ws.parse_header(data_ptr, header_size, false); if (ret == -2) { header_size += ws.left_header_len(); @@ -1725,23 +1759,24 @@ class coro_http_client : public std::enable_shared_from_this { frame_header *header = (frame_header *)data_ptr; bool is_close_frame = header->opcode == opcode::close; - read_buf_.consume(header_size); + read_buf.consume(header_size); size_t payload_len = ws.payload_length(); - if (payload_len > read_buf_.size()) { - size_t size_to_read = payload_len - read_buf_.size(); - if (auto [ec, size] = co_await async_read(read_buf_, size_to_read); + if (payload_len > read_buf.size()) { + size_t size_to_read = payload_len - read_buf.size(); + if (auto [ec, size] = co_await async_read_ws( + sock, read_buf, size_to_read, has_init_ssl); ec) { data.net_err = ec; data.status = 404; - close_socket(*socket_); + close_socket(*sock); if (on_ws_msg) on_ws_msg(data); co_return; } } - data_ptr = asio::buffer_cast(read_buf_.data()); + data_ptr = asio::buffer_cast(read_buf.data()); if (is_close_frame) { payload_len -= 2; data_ptr += sizeof(uint16_t); @@ -1750,14 +1785,24 @@ class coro_http_client : public std::enable_shared_from_this { data.status = 200; data.resp_body = {data_ptr, payload_len}; - read_buf_.consume(read_buf_.size()); + read_buf.consume(read_buf.size()); header_size = 2; if (is_close_frame) { - if (on_ws_close_) - on_ws_close_(data.resp_body); - co_await async_send_ws("close", false, opcode::close); - async_close(); + if (on_ws_close) + on_ws_close(data.resp_body); + + std::string reason = "close"; + auto close_str = ws.format_close_payload(close_code::normal, + reason.data(), reason.size()); + auto span = std::span(close_str); + std::string encode_header = ws.encode_frame(span, opcode::close, false); + std::vector buffers{asio::buffer(encode_header), + asio::buffer(reason)}; + + co_await async_write_ws(sock, buffers, has_init_ssl); + + close_socket(*sock); data.net_err = asio::error::eof; data.status = 404; @@ -1770,11 +1815,42 @@ class coro_http_client : public std::enable_shared_from_this { } } + template + async_simple::coro::Lazy> async_read_ws( + auto sock, AsioBuffer &&buffer, size_t size_to_read, + bool has_init_ssl = false) noexcept { +#ifdef CINATRA_ENABLE_SSL + if (has_init_ssl) { + return coro_io::async_read(*sock->ssl_stream_, buffer, size_to_read); + } + else { +#endif + return coro_io::async_read(sock->impl_, buffer, size_to_read); +#ifdef CINATRA_ENABLE_SSL + } +#endif + } + + template + async_simple::coro::Lazy> async_write_ws( + auto sock, AsioBuffer &&buffer, bool has_init_ssl = false) { +#ifdef CINATRA_ENABLE_SSL + if (has_init_ssl) { + return coro_io::async_write(*sock->ssl_stream_, buffer); + } + else { +#endif + return coro_io::async_write(sock->impl_, buffer); +#ifdef CINATRA_ENABLE_SSL + } +#endif + } + template async_simple::coro::Lazy> async_read( AsioBuffer &&buffer, size_t size_to_read) noexcept { #ifdef CINATRA_ENABLE_SSL - if (use_ssl_) { + if (has_init_ssl_) { return coro_io::async_read(*socket_->ssl_stream_, buffer, size_to_read); } else { @@ -1789,7 +1865,7 @@ class coro_http_client : public std::enable_shared_from_this { async_simple::coro::Lazy> async_write( AsioBuffer &&buffer) { #ifdef CINATRA_ENABLE_SSL - if (use_ssl_) { + if (has_init_ssl_) { return coro_io::async_write(*socket_->ssl_stream_, buffer); } else { @@ -1804,7 +1880,7 @@ class coro_http_client : public std::enable_shared_from_this { async_simple::coro::Lazy> async_read_until( AsioBuffer &buffer, asio::string_view delim) noexcept { #ifdef CINATRA_ENABLE_SSL - if (use_ssl_) { + if (has_init_ssl_) { return coro_io::async_read_until(*socket_->ssl_stream_, buffer, delim); } else { @@ -1881,8 +1957,8 @@ class coro_http_client : public std::enable_shared_from_this { #ifdef CINATRA_ENABLE_SSL std::unique_ptr ssl_ctx_ = nullptr; - bool ssl_init_ret_ = true; - bool use_ssl_ = false; + bool has_init_ssl_ = false; + bool is_ssl_schema_ = false; bool need_set_sni_host_ = true; #endif std::string redirect_uri_; diff --git a/src/coro_http/examples/example.cpp b/src/coro_http/examples/example.cpp index 729428154..9175e6136 100644 --- a/src/coro_http/examples/example.cpp +++ b/src/coro_http/examples/example.cpp @@ -19,6 +19,7 @@ #include "ylt/coro_http/coro_http_server.hpp" using namespace std::chrono_literals; +using namespace coro_http; void test_sync_client() { { @@ -77,7 +78,6 @@ async_simple::coro::Lazy test_async_ssl_client( coro_http::coro_http_client &client) { #ifdef CINATRA_ENABLE_SSL std::string uri = "https://cn.bing.com"; - [[maybe_unused]] auto ec = client.init_ssl("cn.bing.com"); auto data = co_await client.async_get(uri); std::cout << data.net_err.message() << "\n"; std::cout << data.status << std::endl; @@ -87,6 +87,37 @@ async_simple::coro::Lazy test_async_ssl_client( async_simple::coro::Lazy test_websocket( coro_http::coro_http_client &client) { + coro_http_server server(1, 8090); + server.set_http_handler( + "/ws_echo", + [](coro_http_request &req, + coro_http_response &resp) -> async_simple::coro::Lazy { + websocket_result result{}; + + while (true) { + result = co_await req.get_conn()->read_websocket(); + if (result.ec) { + std::cout << "err msg: " << result.ec.message() << "\n"; + break; + } + + if (result.type == ws_frame_type::WS_CLOSE_FRAME) { + std::cout << "close reason: " << result.data << "\n"; + break; + } + + std::cout << "get ws data from client, data content: " << result.data + << "\n"; + + auto ec = co_await req.get_conn()->write_websocket(result.data); + if (ec) { + std::cout << "err msg: " << ec.message() << "\n"; + break; + } + } + }); + server.async_start(); + client.on_ws_close([](std::string_view reason) { std::cout << "web socket close " << reason << std::endl; }); @@ -100,7 +131,7 @@ async_simple::coro::Lazy test_websocket( }); // connect to your websocket server. - bool r = co_await client.async_ws_connect("ws://localhost:8090/ws"); + bool r = co_await client.async_ws_connect("ws://127.0.0.1:8090/ws_echo"); if (!r) { co_return; } @@ -111,34 +142,194 @@ async_simple::coro::Lazy test_websocket( std::cout << result.net_err << "\n"; result = co_await client.async_send_ws_close("ws close"); std::cout << result.net_err << "\n"; + + std::this_thread::sleep_for( + 300ms); // wait for server deal with all messages, avoid server destruct + // immediately. +} + +bool create_file(std::string filename, size_t file_size) { + std::ofstream file(filename, std::ios::binary); + if (!file) { + return false; + } + + std::string str(file_size, 'A'); + file.write(str.data(), str.size()); + return true; } -async_simple::coro::Lazy upload_files( +async_simple::coro::Lazy chunked_upload_download( coro_http::coro_http_client &client) { - client.add_str_part("hello", "world"); - client.add_str_part("key", "value"); - client.add_file_part("test", "test.jpg"); - std::string uri = "http://yoururl.com"; - auto result = co_await client.async_upload_multipart(uri); - std::cout << result.net_err << "\n"; - std::cout << result.status << "\n"; + coro_http_server server(1, 8090); + server.set_http_handler( + "/chunked", + [](coro_http_request &req, + coro_http_response &resp) -> async_simple::coro::Lazy { + assert(req.get_content_type() == content_type::chunked); + chunked_result result{}; + coro_io::coro_file file{}; + size_t total = 0; + co_await file.async_open("test_file", coro_io::flags::create_write); + while (true) { + result = co_await req.get_conn()->read_chunked(); + if (result.ec) { + co_return; + } - result = co_await client.async_upload_multipart(uri, "test", "test.jpg"); - std::cout << result.status << "\n"; + co_await file.async_write(result.data.data(), result.data.size()); + total += result.data.size(); + if (result.eof) { + break; + } + } + + file.close(); + std::cout << "content size: " << fs::file_size("test_file") << "\n"; + resp.set_status_and_content(status_type::ok, "chunked ok"); + }); + + server.set_http_handler( + "/write_chunked", + [](coro_http_request &req, + coro_http_response &resp) -> async_simple::coro::Lazy { + resp.set_format_type(format_type::chunked); + bool ok; + if (ok = co_await resp.get_conn()->begin_chunked(); !ok) { + co_return; + } + + std::vector vec{"hello", " world", " ok"}; + + for (auto &str : vec) { + if (ok = co_await resp.get_conn()->write_chunked(str); !ok) { + co_return; + } + } + + ok = co_await resp.get_conn()->end_chunked(); + + // resp.set_status_and_content(status_type::ok, "chunked ok"); + // co_await resp.get_conn()->reply(); + }); + + server.async_start(); + + std::string filename = "chunked.txt"; + create_file(filename, 1024); + + coro_io::coro_file file{}; + co_await file.async_open(filename, coro_io::flags::read_only); + + std::string buf; + detail::resize(buf, 100); + + auto fn = [&file, &buf]() -> async_simple::coro::Lazy { + auto [ec, size] = co_await file.async_read(buf.data(), buf.size()); + co_return read_result{{buf.data(), size}, file.eof(), ec}; + }; + + auto result = co_await client.async_upload_chunked( + "http://127.0.0.1:8090/chunked"sv, http_method::POST, std::move(fn)); + assert(result.status == 200); + + result = co_await client.async_get("http://127.0.0.1:8090/write_chunked"); + assert(result.status == 200); + assert(result.resp_body == "hello world ok"); } -async_simple::coro::Lazy download_files( +async_simple::coro::Lazy multipart_upload_files( coro_http::coro_http_client &client) { - auto result = co_await client.async_download("http://example.com/test.jpg", - "myfile.jpg"); + coro_http_server server(1, 8090); + server.set_http_handler( + "/multipart_upload", + [](coro_http_request &req, + coro_http_response &resp) -> async_simple::coro::Lazy { + assert(req.get_content_type() == content_type::multipart); + auto boundary = req.get_boundary(); + + while (true) { + auto part_head = co_await req.get_conn()->read_part_head(); + if (part_head.ec) { + co_return; + } + + std::cout << part_head.name << "\n"; + std::cout << part_head.filename << "\n"; + + std::shared_ptr file; + std::string filename; + if (!part_head.filename.empty()) { + file = std::make_shared(); + filename = std::to_string( + std::chrono::system_clock::now().time_since_epoch().count()); + + size_t pos = part_head.filename.rfind('.'); + if (pos != std::string::npos) { + auto extent = part_head.filename.substr(pos); + filename += extent; + } + + std::cout << filename << "\n"; + co_await file->async_open(filename, coro_io::flags::create_write); + if (!file->is_open()) { + resp.set_status_and_content(status_type::internal_server_error, + "file open failed"); + co_return; + } + } + + auto part_body = co_await req.get_conn()->read_part_body(boundary); + if (part_body.ec) { + co_return; + } + + if (!filename.empty()) { + auto ec = co_await file->async_write(part_body.data.data(), + part_body.data.size()); + if (ec) { + co_return; + } + + file->close(); + assert(fs::file_size(filename) == 1024); + } + else { + std::cout << part_body.data << "\n"; + } + + if (part_body.eof) { + break; + } + } + + resp.set_status_and_content(status_type::ok, "ok"); + co_return; + }); + + server.async_start(); + + std::string filename = "test_1024.txt"; + create_file(filename, 1024); + + client.add_str_part("test", "test value"); + client.add_file_part("test file", filename); + + std::string uri = "http://127.0.0.1:8090/multipart_upload"; + auto result = co_await client.async_upload_multipart(uri); + std::cout << result.status << "\n"; } async_simple::coro::Lazy ranges_download_files( coro_http::coro_http_client &client) { - auto result = co_await client.async_download("http://example.com/test.txt", - "myfile.txt", "1-10,11-16"); + auto result = co_await client.async_download( + "http://uniquegoodshiningmelody.neverssl.com/favicon.ico", "myfile", + "1-10,11-16"); std::cout << result.status << "\n"; + if (result.status == 206 && !result.resp_body.empty()) { + assert(fs::file_size("myfile") == 16); + } } void use_out_buf() { @@ -224,7 +415,7 @@ void test_coro_http_server() { int main() { test_coro_http_server(); test_sync_client(); - // use_out_buf(); + use_out_buf(); coro_http::coro_http_client client{}; async_simple::coro::syncAwait(test_async_client(client)); @@ -235,15 +426,14 @@ int main() { coro_http::coro_http_client ws_client{}; async_simple::coro::syncAwait(test_websocket(ws_client)); + coro_http_client chunked_client{}; + async_simple::coro::syncAwait(chunked_upload_download(chunked_client)); + coro_http::coro_http_client upload_client{}; upload_client.set_req_timeout(std::chrono::seconds(3)); - async_simple::coro::syncAwait(upload_files(upload_client)); - - coro_http::coro_http_client download_client{}; - download_client.set_req_timeout(std::chrono::seconds(3)); - async_simple::coro::syncAwait(download_files(download_client)); + async_simple::coro::syncAwait(multipart_upload_files(upload_client)); coro_http::coro_http_client ranges_download_client{}; - ranges_download_client.set_req_timeout(std::chrono::seconds(3)); + ranges_download_client.set_req_timeout(std::chrono::seconds(10)); async_simple::coro::syncAwait(ranges_download_files(ranges_download_client)); } \ No newline at end of file