From 1278e2d3e66e28f5ee275a4b8b804a3f2a82f669 Mon Sep 17 00:00:00 2001 From: qicosmos Date: Thu, 14 Dec 2023 16:58:11 +0800 Subject: [PATCH] update coro_http_server --- include/ylt/coro_io/coro_file.hpp | 12 +++-- .../thirdparty/cinatra/coro_http_server.hpp | 52 +++++++++++++++++-- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/include/ylt/coro_io/coro_file.hpp b/include/ylt/coro_io/coro_file.hpp index 99ac4d4b1..a45633b67 100644 --- a/include/ylt/coro_io/coro_file.hpp +++ b/include/ylt/coro_io/coro_file.hpp @@ -270,6 +270,7 @@ class coro_file { async_simple::coro::Lazy> async_read_at( uint64_t offset, char* data, size_t size) { assert(stream_file_); + assert(type_ == read_type::uring_random); auto [ec, read_size] = co_await coro_io::async_read_at( offset, @@ -288,6 +289,7 @@ class coro_file { const char* data, size_t size) { assert(stream_file_); + assert(type_ == read_type::uring_random); auto [ec, write_size] = co_await coro_io::async_write_at( offset, @@ -299,6 +301,7 @@ class coro_file { async_simple::coro::Lazy> async_read( char* data, size_t size) { assert(stream_file_); + assert(type_ == read_type::uring); auto [ec, read_size] = co_await coro_io::async_read( *reinterpret_cast(stream_file_.get()), @@ -314,6 +317,7 @@ class coro_file { async_simple::coro::Lazy async_write(const char* data, size_t size) { assert(stream_file_); + assert(type_ == read_type::uring); auto [ec, write_size] = co_await coro_io::async_write( *reinterpret_cast(stream_file_.get()), @@ -325,20 +329,20 @@ class coro_file { std::string str_mode(int open_mode) { switch (open_mode) { case flags::read_only: - return "r"; + return "rb"; case flags::create_write: case flags::write_only: return "w"; case flags::read_write: - return "r+"; + return "rb+"; case flags::append: return "a"; case flags::create_read_write_append: - return "a+"; + return "ab+"; case flags::truncate: return "w+"; default: - return "r+"; + return "rb+"; } } diff --git a/include/ylt/thirdparty/cinatra/coro_http_server.hpp b/include/ylt/thirdparty/cinatra/coro_http_server.hpp index bd635b893..6225325db 100644 --- a/include/ylt/thirdparty/cinatra/coro_http_server.hpp +++ b/include/ylt/thirdparty/cinatra/coro_http_server.hpp @@ -17,6 +17,10 @@ #include "ylt/coro_io/io_context_pool.hpp" namespace cinatra { +enum class file_resp_format_type { + chunked, + range, +}; class coro_http_server { public: coro_http_server(asio::io_context &ctx, unsigned short port) @@ -151,6 +155,35 @@ class coro_http_server { } } + void set_max_size_of_cache_files(size_t max_size = 3 * 1024 * 1024) { + std::error_code ec; + for (const auto &file : + std::filesystem::recursive_directory_iterator(static_dir_, ec)) { + if (ec) { + continue; + } + + if (!file.is_directory()) { + size_t filesize = fs::file_size(file, ec); + if (ec || filesize > max_size) { + continue; + } + + std::ifstream ifs(file.path(), std::ios::binary); + if (ifs.is_open()) { + std::string content; + detail::resize(content, filesize); + ifs.read(content.data(), content.size()); + static_file_cache_.emplace(file.path().string(), std::move(content)); + } + } + } + } + + void set_file_resp_format_type(file_resp_format_type type) { + format_type_ = type; + } + void set_transfer_chunked_size(size_t size) { chunked_size_ = size; } void set_static_res_handler(std::string_view uri_suffix = "", @@ -202,11 +235,21 @@ class coro_http_server { [this, file_name = file]( coro_http_request &req, coro_http_response &resp) -> async_simple::coro::Lazy { - bool is_ranges = req.is_req_ranges(); - std::string_view extension = get_extension(file_name); std::string_view mime = get_mime_type(extension); + if (auto it = static_file_cache_.find(file_name); + it != static_file_cache_.end()) { + auto range_header = + build_range_header(mime, file_name, fs::file_size(file_name)); + resp.set_delay(true); + std::string &body = it->second; + std::array arr{asio::buffer(range_header), + asio::buffer(body)}; + co_await req.get_conn()->async_write(arr); + co_return; + } + std::string content; detail::resize(content, chunked_size_); @@ -218,7 +261,7 @@ class coro_http_server { co_return; } - if (!is_ranges) { + if (format_type_ == file_resp_format_type::chunked) { resp.set_format_type(format_type::chunked); bool ok; if (ok = co_await resp.get_conn()->begin_chunked(); !ok) { @@ -473,6 +516,9 @@ class coro_http_server { std::string static_dir_ = ""; std::vector files_; size_t chunked_size_ = 1024 * 10; + + std::unordered_map static_file_cache_; + file_resp_format_type format_type_ = file_resp_format_type::chunked; #ifdef CINATRA_ENABLE_SSL std::string cert_file_; std::string key_file_;