diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-05-05 17:03:26 +0300 |
---|---|---|
committer | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-05-05 17:03:26 +0300 |
commit | b94ffc4f9fb0de2cccb10069715302687b494c34 (patch) | |
tree | 0a992a17f01285d3976b78bd57be64a3691e9a59 | |
parent | f8831bfbf91cd9e5f400dbc59372651bf756d87a (diff) | |
download | ydb-b94ffc4f9fb0de2cccb10069715302687b494c34.tar.gz |
intermediate changes
ref:670915a6a4cf5edb3a63ce999d592acd20f1f248
-rw-r--r-- | build/rules/autocheck.blacklist | 2 | ||||
-rw-r--r-- | library/cpp/actors/http/CMakeLists.txt | 1 | ||||
-rw-r--r-- | library/cpp/actors/http/http.cpp | 2 | ||||
-rw-r--r-- | library/cpp/actors/http/http.h | 99 | ||||
-rw-r--r-- | library/cpp/actors/http/http_compress.cpp | 42 | ||||
-rw-r--r-- | library/cpp/actors/http/http_ut.cpp | 14 |
6 files changed, 125 insertions, 35 deletions
diff --git a/build/rules/autocheck.blacklist b/build/rules/autocheck.blacklist index 0b3fde6b40e..7f811535479 100644 --- a/build/rules/autocheck.blacklist +++ b/build/rules/autocheck.blacklist @@ -1416,3 +1416,5 @@ admins/icecream/node-icecream adv/pcode/mobileadssdk/sdk/ios/library admins/icecream/agent trunk/arcadia/crm/space/frontend_static +crm/space/frontend_static +samsara/samsara-poll diff --git a/library/cpp/actors/http/CMakeLists.txt b/library/cpp/actors/http/CMakeLists.txt index 5f8197e3c6c..166af4cec53 100644 --- a/library/cpp/actors/http/CMakeLists.txt +++ b/library/cpp/actors/http/CMakeLists.txt @@ -21,6 +21,7 @@ target_link_libraries(cpp-actors-http PUBLIC ) target_sources(cpp-actors-http PRIVATE ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_cache.cpp + ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_compress.cpp ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_proxy_acceptor.cpp ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_proxy_incoming.cpp ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_proxy_outgoing.cpp diff --git a/library/cpp/actors/http/http.cpp b/library/cpp/actors/http/http.cpp index 3d07c870ced..09381d0fb3e 100644 --- a/library/cpp/actors/http/http.cpp +++ b/library/cpp/actors/http/http.cpp @@ -30,6 +30,7 @@ template <> TStringBuf THttpRequest::GetName<&THttpRequest::Connection>() { retu template <> TStringBuf THttpRequest::GetName<&THttpRequest::ContentType>() { return "Content-Type"; } template <> TStringBuf THttpRequest::GetName<&THttpRequest::ContentLength>() { return "Content-Length"; } template <> TStringBuf THttpRequest::GetName<&THttpRequest::TransferEncoding>() { return "Transfer-Encoding"; } +template <> TStringBuf THttpRequest::GetName<&THttpRequest::AcceptEncoding>() { return "Accept-Encoding"; } const TMap<TStringBuf, TStringBuf THttpRequest::*, TLessNoCase> THttpRequest::HeadersLocation = { { THttpRequest::GetName<&THttpRequest::Host>(), &THttpRequest::Host }, @@ -38,6 +39,7 @@ const TMap<TStringBuf, TStringBuf THttpRequest::*, TLessNoCase> THttpRequest::He { THttpRequest::GetName<&THttpRequest::ContentType>(), &THttpRequest::ContentType }, { THttpRequest::GetName<&THttpRequest::ContentLength>(), &THttpRequest::ContentLength }, { THttpRequest::GetName<&THttpRequest::TransferEncoding>(), &THttpRequest::TransferEncoding }, + { THttpRequest::GetName<&THttpRequest::AcceptEncoding>(), &THttpRequest::AcceptEncoding }, }; template <> TStringBuf THttpResponse::GetName<&THttpResponse::Connection>() { return "Connection"; } diff --git a/library/cpp/actors/http/http.h b/library/cpp/actors/http/http.h index 3e5e39e7194..6d51cf589c2 100644 --- a/library/cpp/actors/http/http.h +++ b/library/cpp/actors/http/http.h @@ -130,6 +130,7 @@ public: TStringBuf Connection; TStringBuf ContentType; TStringBuf ContentLength; + TStringBuf AcceptEncoding; TStringBuf TransferEncoding; TStringBuf Body; @@ -200,7 +201,7 @@ public: TStringBuf& Header = Line; size_t ChunkLength = 0; size_t ContentSize = 0; - TString Content; + TString Content; // body storage std::optional<size_t> TotalSize; THttpParser(const THttpParser& src) @@ -436,6 +437,36 @@ public: ERenderStage Stage = ERenderStage::Init; + //THttpRenderer(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version); // request + void InitRequest(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version) { + Y_VERIFY_DEBUG(Stage == ERenderStage::Init); + AppendParsedValue<&THttpRequest::Method>(method); + Append(' '); + AppendParsedValue<&THttpRequest::URL>(url); + Append(' '); + AppendParsedValue<&THttpRequest::Protocol>(protocol); + Append('/'); + AppendParsedValue<&THttpRequest::Version>(version); + Append("\r\n"); + Stage = ERenderStage::Header; + HeaderType::Headers = TStringBuf(BufferType::Pos(), size_t(0)); + } + + //THttpRenderer(TStringBuf protocol, TStringBuf version, TStringBuf status, TStringBuf message); // response + void InitResponse(TStringBuf protocol, TStringBuf version, TStringBuf status, TStringBuf message) { + Y_VERIFY_DEBUG(Stage == ERenderStage::Init); + AppendParsedValue<&THttpResponse::Protocol>(protocol); + Append('/'); + AppendParsedValue<&THttpResponse::Version>(version); + Append(' '); + AppendParsedValue<&THttpResponse::Status>(status); + Append(' '); + AppendParsedValue<&THttpResponse::Message>(message); + Append("\r\n"); + Stage = ERenderStage::Header; + HeaderType::Headers = TStringBuf(BufferType::Pos(), size_t(0)); + } + void Append(TStringBuf text) { EnsureEnoughSpaceAvailable(text.size()); BufferType::Append(text.data(), text.size()); @@ -484,34 +515,13 @@ public: HeaderType::Headers = TStringBuf(HeaderType::Headers.Data(), BufferType::Pos() - HeaderType::Headers.Data()); } - //THttpRenderer(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version); // request - void InitRequest(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version) { - Y_VERIFY_DEBUG(Stage == ERenderStage::Init); - AppendParsedValue<&THttpRequest::Method>(method); - Append(' '); - AppendParsedValue<&THttpRequest::URL>(url); - Append(' '); - AppendParsedValue<&THttpRequest::Protocol>(protocol); - Append('/'); - AppendParsedValue<&THttpRequest::Version>(version); - Append("\r\n"); - Stage = ERenderStage::Header; - HeaderType::Headers = TStringBuf(BufferType::Pos(), size_t(0)); - } + static constexpr TStringBuf ALLOWED_CONTENT_ENCODINGS[] = {"deflate"}; - //THttpRenderer(TStringBuf protocol, TStringBuf version, TStringBuf status, TStringBuf message); // response - void InitResponse(TStringBuf protocol, TStringBuf version, TStringBuf status, TStringBuf message) { - Y_VERIFY_DEBUG(Stage == ERenderStage::Init); - AppendParsedValue<&THttpResponse::Protocol>(protocol); - Append('/'); - AppendParsedValue<&THttpResponse::Version>(version); - Append(' '); - AppendParsedValue<&THttpResponse::Status>(status); - Append(' '); - AppendParsedValue<&THttpResponse::Message>(message); - Append("\r\n"); - Stage = ERenderStage::Header; - HeaderType::Headers = TStringBuf(BufferType::Pos(), size_t(0)); + void SetContentEncoding(TStringBuf contentEncoding) { + Y_VERIFY_DEBUG(Stage == ERenderStage::Header); + if (Count(ALLOWED_CONTENT_ENCODINGS, contentEncoding) != 0) { + Set("Content-Encoding", contentEncoding); + } } void FinishHeader() { @@ -621,6 +631,12 @@ inline void THttpRenderer<THttpRequest, TSocketBuffer>::Set<&THttpRequest::Body> SetBody(value); } +template <> +template <> +inline void THttpRenderer<THttpResponse, TSocketBuffer>::Set<&THttpResponse::ContentEncoding>(TStringBuf value) { + SetContentEncoding(value); +} + class THttpIncomingRequest; using THttpIncomingRequestPtr = TIntrusivePtr<THttpIncomingRequest>; @@ -730,6 +746,33 @@ public: return GetRequest()->Method != "HEAD" && Status != "204"; } + void EnableCompression() { + TStringBuf acceptEncoding = Request->AcceptEncoding; + std::vector<TStringBuf> encodings; + TStringBuf encoding; + while (acceptEncoding.NextTok(',', encoding)) { + Trim(encoding, ' '); + if (Count(ALLOWED_CONTENT_ENCODINGS, encoding) != 0) { + encodings.push_back(encoding); + } + } + if (!encodings.empty()) { + // TODO: prioritize encodings + SetContentEncoding(encodings.front()); + } + } + + static TString CompressDeflate(TStringBuf source); + + void SetBody(TStringBuf body) { + if (ContentEncoding == "deflate") { + TString compressedBody = CompressDeflate(body); + THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(compressedBody); + } else { + THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(body); + } + } + THttpIncomingRequestPtr GetRequest() const { return Request; } diff --git a/library/cpp/actors/http/http_compress.cpp b/library/cpp/actors/http/http_compress.cpp new file mode 100644 index 00000000000..33ff3e16746 --- /dev/null +++ b/library/cpp/actors/http/http_compress.cpp @@ -0,0 +1,42 @@ +#include "http.h" + +#include <contrib/libs/zlib/zlib.h> + +namespace NHttp { + +TString THttpOutgoingResponse::CompressDeflate(TStringBuf source) { + int compressionlevel = Z_BEST_COMPRESSION; + z_stream zs = {}; + + if (deflateInit(&zs, compressionlevel) != Z_OK) { + throw yexception() << "deflateInit failed while compressing"; + } + + zs.next_in = (Bytef*)source.data(); + zs.avail_in = source.size(); + + int ret; + char outbuffer[32768]; + TString result; + + // retrieve the compressed bytes blockwise + do { + zs.next_out = reinterpret_cast<Bytef*>(outbuffer); + zs.avail_out = sizeof(outbuffer); + + ret = deflate(&zs, Z_FINISH); + + if (result.size() < zs.total_out) { + result.append(outbuffer, zs.total_out - result.size()); + } + } while (ret == Z_OK); + + deflateEnd(&zs); + + if (ret != Z_STREAM_END) { + throw yexception() << "Exception during zlib compression: (" << ret << ") " << zs.msg; + } + return result; +} + +} diff --git a/library/cpp/actors/http/http_ut.cpp b/library/cpp/actors/http/http_ut.cpp index cdb9025ff17..4ec7761da91 100644 --- a/library/cpp/actors/http/http_ut.cpp +++ b/library/cpp/actors/http/http_ut.cpp @@ -96,15 +96,15 @@ Y_UNIT_TEST_SUITE(HttpProxy) { UNIT_ASSERT_EQUAL(response->Body, "this\r\n is test."); } - Y_UNIT_TEST(CreateResponseWithCompressedBody) { - NHttp::THttpIncomingRequestPtr request = nullptr; + Y_UNIT_TEST(CreateCompressedResponse) { + NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); + EatWholeString(request, "GET /Url HTTP/1.1\r\nConnection: close\r\nAccept-Encoding: gzip, deflate\r\n\r\n"); NHttp::THttpOutgoingResponsePtr response = new NHttp::THttpOutgoingResponse(request, "HTTP", "1.1", "200", "OK"); - response->Set<&NHttp::THttpResponse::ContentEncoding>("gzip"); - TString compressedBody = "compressed body"; + TString compressedBody = "something very long to compress with deflate algorithm. something very long to compress with deflate algorithm."; + response->EnableCompression(); response->SetBody(compressedBody); - UNIT_ASSERT_VALUES_EQUAL("gzip", response->ContentEncoding); - UNIT_ASSERT_VALUES_EQUAL(ToString(compressedBody.size()), response->ContentLength); - UNIT_ASSERT_VALUES_EQUAL(compressedBody, response->Body); + UNIT_ASSERT_VALUES_EQUAL("deflate", response->ContentEncoding); + UNIT_ASSERT_VALUES_UNEQUAL(compressedBody, response->Body); } Y_UNIT_TEST(BasicPartialParsing) { |