From c46cbf54ccf7676b59b8418e2e822d5f1687e176 Mon Sep 17 00:00:00 2001 From: helintong Date: Tue, 11 Jun 2024 19:05:16 +0800 Subject: [PATCH] feat: add multiple encoding type support --- include/cinatra/coro_http_client.hpp | 6 ++- include/cinatra/coro_http_request.hpp | 4 ++ include/cinatra/coro_http_response.hpp | 59 ++++++++++++++++++-------- tests/test_cinatra.cpp | 28 +++++++++++- 4 files changed, 76 insertions(+), 21 deletions(-) diff --git a/include/cinatra/coro_http_client.hpp b/include/cinatra/coro_http_client.hpp index ade32d24..858f3d64 100644 --- a/include/cinatra/coro_http_client.hpp +++ b/include/cinatra/coro_http_client.hpp @@ -1438,9 +1438,11 @@ class coro_http_client : public std::enable_shared_from_this { #ifdef CINATRA_ENABLE_GZIP if (!parser_.get_header_value("Content-Encoding").empty()) { - if (parser_.get_header_value("Content-Encoding") == "gzip") + 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") == "deflate") + else if (parser_.get_header_value("Content-Encoding").find("deflate") != + std::string_view::npos) encoding_type_ = content_encoding::deflate; } else { diff --git a/include/cinatra/coro_http_request.hpp b/include/cinatra/coro_http_request.hpp index b3c08797..5b643c17 100644 --- a/include/cinatra/coro_http_request.hpp +++ b/include/cinatra/coro_http_request.hpp @@ -145,6 +145,10 @@ class coro_http_request { bool is_req_ranges() { return parser_.is_req_ranges(); } + std::string get_accept_encoding() { + return std::string(get_header_value("Accept-Encoding")); + } + content_encoding get_encoding_type() { auto encoding_type = get_header_value("Content-Encoding"); if (!encoding_type.empty()) { diff --git a/include/cinatra/coro_http_response.hpp b/include/cinatra/coro_http_response.hpp index 9505c0da..93c28284 100644 --- a/include/cinatra/coro_http_response.hpp +++ b/include/cinatra/coro_http_response.hpp @@ -52,38 +52,63 @@ class coro_http_response { } void set_status_and_content( status_type status, std::string content = "", - content_encoding encoding = content_encoding::none) { - set_status_and_content_view(status, std::move(content), encoding, false); + content_encoding encoding = content_encoding::none, + std::string client_encoding_type = "") { + set_status_and_content_view(status, std::move(content), encoding, false, + client_encoding_type); } template void set_status_and_content_view( status_type status, String content = "", - content_encoding encoding = content_encoding::none, bool is_view = true) { + content_encoding encoding = content_encoding::none, bool is_view = true, + std::string_view client_encoding_type = "") { status_ = status; #ifdef CINATRA_ENABLE_GZIP if (encoding == content_encoding::gzip) { - std::string encode_str; - bool r = gzip_codec::compress(content, encode_str, true); - if (!r) { - set_status_and_content(status_type::internal_server_error, - "gzip compress error"); + if (client_encoding_type.empty() || + client_encoding_type.find("gzip") != std::string_view::npos) { + std::string encode_str; + bool r = gzip_codec::compress(content, encode_str, true); + if (!r) { + set_status_and_content(status_type::internal_server_error, + "gzip compress error"); + } + else { + add_header("Content-Encoding", "gzip"); + set_content(std::move(encode_str)); + } } else { - add_header("Content-Encoding", "gzip"); - set_content(std::move(encode_str)); + if (is_view) { + content_view_ = content; + } + else { + content_ = std::move(content); + } } } else if (encoding == content_encoding::deflate) { - std::string deflate_str; - bool r = gzip_codec::deflate(content, deflate_str); - if (!r) { - set_status_and_content(status_type::internal_server_error, - "deflate compress error"); + if (client_encoding_type.empty() || + client_encoding_type.find("deflate") != std::string_view::npos) { + std::string deflate_str; + bool r = gzip_codec::deflate(content, deflate_str); + if (!r) { + set_status_and_content(status_type::internal_server_error, + "deflate compress error"); + } + else { + add_header("Content-Encoding", "deflate"); + set_content(std::move(deflate_str)); + } } else { - add_header("Content-Encoding", "deflate"); - set_content(std::move(deflate_str)); + if (is_view) { + content_view_ = content; + } + else { + content_ = std::move(content); + } } } else diff --git a/tests/test_cinatra.cpp b/tests/test_cinatra.cpp index 9b2b7e8a..96eb12a8 100644 --- a/tests/test_cinatra.cpp +++ b/tests/test_cinatra.cpp @@ -70,7 +70,9 @@ TEST_CASE("test encoding type") { bool r = gzip_codec::uncompress(req.get_body(), decode_str); CHECK(decode_str == "Hello World"); } - resp.set_status_and_content(status_type::ok, "ok", content_encoding::gzip); + resp.set_status_and_content(status_type::ok, "ok", content_encoding::gzip, + req.get_accept_encoding()); + CHECK(resp.content() != "ok"); }); server.set_http_handler( @@ -78,7 +80,22 @@ TEST_CASE("test encoding type") { [](coro_http_request &req, coro_http_response &resp) -> async_simple::coro::Lazy { resp.set_status_and_content(status_type::ok, "ok", - content_encoding::deflate); + content_encoding::deflate, + req.get_accept_encoding()); + CHECK(resp.content() != "ok"); + co_return; + }); + + server.set_http_handler( + "/only_gzip", + [](coro_http_request &req, + coro_http_response &resp) -> async_simple::coro::Lazy { + resp.set_status_and_content(status_type::ok, "ok", + content_encoding::gzip, + req.get_accept_encoding()); + // client4 accept-encoding not allow gzip, response content no + // compression + CHECK(resp.content() == "ok"); co_return; }); @@ -107,6 +124,13 @@ TEST_CASE("test encoding type") { result = async_simple::coro::syncAwait(client3.async_post( "http://127.0.0.1:9001/get", ziped_str, req_content_type::none, headers)); CHECK(result.resp_body == "ok"); + + coro_http_client client4{}; + client4.add_header("Accept-Encoding", "deflate"); + result = async_simple::coro::syncAwait( + client4.async_get("http://127.0.0.1:9001/only_gzip")); + CHECK(result.resp_body == "ok"); + server.stop(); } #endif