diff options
| author | robot-piglet <[email protected]> | 2023-12-04 15:32:14 +0300 |
|---|---|---|
| committer | robot-piglet <[email protected]> | 2023-12-05 01:22:50 +0300 |
| commit | c21ed9eedf73010bc81342518177dfdfb0d56bd7 (patch) | |
| tree | 72f8fde4463080cfe5a38eb0babc051cfe32c51e /library/cpp/actors/http | |
| parent | ec1311bf2e8cc231723b8b5e484ca576663a1309 (diff) | |
Intermediate changes
Diffstat (limited to 'library/cpp/actors/http')
31 files changed, 0 insertions, 5603 deletions
diff --git a/library/cpp/actors/http/CMakeLists.darwin-arm64.txt b/library/cpp/actors/http/CMakeLists.darwin-arm64.txt deleted file mode 100644 index 1947b6fa393..00000000000 --- a/library/cpp/actors/http/CMakeLists.darwin-arm64.txt +++ /dev/null @@ -1,32 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - -add_subdirectory(ut) - -add_library(cpp-actors-http) -target_link_libraries(cpp-actors-http PUBLIC - contrib-libs-cxxsupp - yutil - contrib-libs-openssl - contrib-libs-zlib - cpp-actors-core - cpp-actors-interconnect - library-cpp-dns - cpp-monlib-metrics - cpp-string_utils-quote -) -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 - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_proxy.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_static.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http.cpp -) diff --git a/library/cpp/actors/http/CMakeLists.darwin-x86_64.txt b/library/cpp/actors/http/CMakeLists.darwin-x86_64.txt deleted file mode 100644 index 1947b6fa393..00000000000 --- a/library/cpp/actors/http/CMakeLists.darwin-x86_64.txt +++ /dev/null @@ -1,32 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - -add_subdirectory(ut) - -add_library(cpp-actors-http) -target_link_libraries(cpp-actors-http PUBLIC - contrib-libs-cxxsupp - yutil - contrib-libs-openssl - contrib-libs-zlib - cpp-actors-core - cpp-actors-interconnect - library-cpp-dns - cpp-monlib-metrics - cpp-string_utils-quote -) -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 - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_proxy.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_static.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http.cpp -) diff --git a/library/cpp/actors/http/CMakeLists.linux-aarch64.txt b/library/cpp/actors/http/CMakeLists.linux-aarch64.txt deleted file mode 100644 index a0e186fa077..00000000000 --- a/library/cpp/actors/http/CMakeLists.linux-aarch64.txt +++ /dev/null @@ -1,33 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - -add_subdirectory(ut) - -add_library(cpp-actors-http) -target_link_libraries(cpp-actors-http PUBLIC - contrib-libs-linux-headers - contrib-libs-cxxsupp - yutil - contrib-libs-openssl - contrib-libs-zlib - cpp-actors-core - cpp-actors-interconnect - library-cpp-dns - cpp-monlib-metrics - cpp-string_utils-quote -) -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 - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_proxy.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_static.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http.cpp -) diff --git a/library/cpp/actors/http/CMakeLists.linux-x86_64.txt b/library/cpp/actors/http/CMakeLists.linux-x86_64.txt deleted file mode 100644 index a0e186fa077..00000000000 --- a/library/cpp/actors/http/CMakeLists.linux-x86_64.txt +++ /dev/null @@ -1,33 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - -add_subdirectory(ut) - -add_library(cpp-actors-http) -target_link_libraries(cpp-actors-http PUBLIC - contrib-libs-linux-headers - contrib-libs-cxxsupp - yutil - contrib-libs-openssl - contrib-libs-zlib - cpp-actors-core - cpp-actors-interconnect - library-cpp-dns - cpp-monlib-metrics - cpp-string_utils-quote -) -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 - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_proxy.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_static.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http.cpp -) diff --git a/library/cpp/actors/http/CMakeLists.txt b/library/cpp/actors/http/CMakeLists.txt deleted file mode 100644 index 2dce3a77fe3..00000000000 --- a/library/cpp/actors/http/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - -if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA) - include(CMakeLists.linux-aarch64.txt) -elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - include(CMakeLists.darwin-x86_64.txt) -elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") - include(CMakeLists.darwin-arm64.txt) -elseif (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" AND NOT HAVE_CUDA) - include(CMakeLists.windows-x86_64.txt) -elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA) - include(CMakeLists.linux-x86_64.txt) -endif() diff --git a/library/cpp/actors/http/CMakeLists.windows-x86_64.txt b/library/cpp/actors/http/CMakeLists.windows-x86_64.txt deleted file mode 100644 index 1947b6fa393..00000000000 --- a/library/cpp/actors/http/CMakeLists.windows-x86_64.txt +++ /dev/null @@ -1,32 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - -add_subdirectory(ut) - -add_library(cpp-actors-http) -target_link_libraries(cpp-actors-http PUBLIC - contrib-libs-cxxsupp - yutil - contrib-libs-openssl - contrib-libs-zlib - cpp-actors-core - cpp-actors-interconnect - library-cpp-dns - cpp-monlib-metrics - cpp-string_utils-quote -) -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 - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_proxy.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_static.cpp - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http.cpp -) diff --git a/library/cpp/actors/http/http.cpp b/library/cpp/actors/http/http.cpp deleted file mode 100644 index 9da46e412bb..00000000000 --- a/library/cpp/actors/http/http.cpp +++ /dev/null @@ -1,823 +0,0 @@ -#include "http.h" -#include <library/cpp/string_utils/quote/quote.h> - -inline TStringBuf operator +(TStringBuf l, TStringBuf r) { - if (l.empty()) { - return r; - } - if (r.empty()) { - return l; - } - if (l.end() == r.begin()) { - return TStringBuf(l.data(), l.size() + r.size()); - } - if (r.end() == l.begin()) { - return TStringBuf(r.data(), l.size() + r.size()); - } - Y_ABORT("oops"); - return TStringBuf(); -} - -inline TStringBuf operator +=(TStringBuf& l, TStringBuf r) { - return l = l + r; -} - -static bool is_not_number(TStringBuf v) { - return v.empty() || std::find_if_not(v.begin(), v.end(), [](unsigned char c) { return std::isdigit(c); }) != v.end(); -} - -namespace NHttp { - -template <> TStringBuf THttpRequest::GetName<&THttpRequest::Host>() { return "Host"; } -template <> TStringBuf THttpRequest::GetName<&THttpRequest::Accept>() { return "Accept"; } -template <> TStringBuf THttpRequest::GetName<&THttpRequest::Connection>() { return "Connection"; } -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 }, - { THttpRequest::GetName<&THttpRequest::Accept>(), &THttpRequest::Accept }, - { THttpRequest::GetName<&THttpRequest::Connection>(), &THttpRequest::Connection }, - { 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"; } -template <> TStringBuf THttpResponse::GetName<&THttpResponse::ContentType>() { return "Content-Type"; } -template <> TStringBuf THttpResponse::GetName<&THttpResponse::ContentLength>() { return "Content-Length"; } -template <> TStringBuf THttpResponse::GetName<&THttpResponse::TransferEncoding>() { return "Transfer-Encoding"; } -template <> TStringBuf THttpResponse::GetName<&THttpResponse::LastModified>() { return "Last-Modified"; } -template <> TStringBuf THttpResponse::GetName<&THttpResponse::ContentEncoding>() { return "Content-Encoding"; } - -const TMap<TStringBuf, TStringBuf THttpResponse::*, TLessNoCase> THttpResponse::HeadersLocation = { - { THttpResponse::GetName<&THttpResponse::Connection>(), &THttpResponse::Connection }, - { THttpResponse::GetName<&THttpResponse::ContentType>(), &THttpResponse::ContentType }, - { THttpResponse::GetName<&THttpResponse::ContentLength>(), &THttpResponse::ContentLength }, - { THttpResponse::GetName<&THttpResponse::TransferEncoding>(), &THttpResponse::TransferEncoding }, - { THttpResponse::GetName<&THttpResponse::LastModified>(), &THttpResponse::LastModified }, - { THttpResponse::GetName<&THttpResponse::ContentEncoding>(), &THttpResponse::ContentEncoding } -}; - -void THttpRequest::Clear() { - // a dirty little trick - this->~THttpRequest(); // basically, do nothing - new (this) THttpRequest(); // reset all fields -} - -template <> -bool THttpParser<THttpRequest, TSocketBuffer>::HaveBody() const { - if (!Body.empty()) { - return true; - } - return !ContentLength.empty() || !TransferEncoding.empty(); -} - -template <> -void THttpParser<THttpRequest, TSocketBuffer>::Advance(size_t len) { - TStringBuf data(Pos(), len); - while (!data.empty()) { - if (Stage != EParseStage::Error) { - LastSuccessStage = Stage; - } - switch (Stage) { - case EParseStage::Method: { - if (ProcessData(Method, data, ' ', MaxMethodSize)) { - Stage = EParseStage::URL; - } - break; - } - case EParseStage::URL: { - if (ProcessData(URL, data, ' ', MaxURLSize)) { - Stage = EParseStage::Protocol; - } - break; - } - case EParseStage::Protocol: { - if (ProcessData(Protocol, data, '/', MaxProtocolSize)) { - Stage = EParseStage::Version; - } - break; - } - case EParseStage::Version: { - if (ProcessData(Version, data, "\r\n", MaxVersionSize)) { - Stage = EParseStage::Header; - Headers = data; - } - break; - } - case EParseStage::Header: { - if (ProcessData(Header, data, "\r\n", MaxHeaderSize)) { - if (Header.empty()) { - if (HaveBody() && (ContentLength.empty() || ContentLength != "0")) { - Stage = EParseStage::Body; - } else if (TotalSize.has_value() && !data.empty()) { - Stage = EParseStage::Body; - } else { - Stage = EParseStage::Done; - } - } else { - ProcessHeader(Header); - } - Headers = TStringBuf(Headers.data(), data.data() - Headers.data()); - } - if (Stage != EParseStage::Body) { - break; - } - [[fallthrough]]; - } - case EParseStage::Body: { - if (TEqNoCase()(TransferEncoding, "chunked")) { - Stage = EParseStage::ChunkLength; - } else if (!ContentLength.empty()) { - if (is_not_number(ContentLength)) { - // Invalid content length - Stage = EParseStage::Error; - } else if (ProcessData(Content, data, FromStringWithDefault(ContentLength, 0))) { - Body = Content; - Stage = EParseStage::Done; - } - } else if (TotalSize.has_value()) { - if (ProcessData(Content, data, GetBodySizeFromTotalSize())) { - Body = Content; - Stage = EParseStage::Done; - } - } else { - // Invalid body encoding - Stage = EParseStage::Error; - } - break; - } - case EParseStage::ChunkLength: { - if (ProcessData(Line, data, "\r\n", MaxChunkLengthSize)) { - if (!Line.empty()) { - ChunkLength = ParseHex(Line); - if (ChunkLength <= MaxChunkSize) { - ContentSize = Content.size() + ChunkLength; - if (ContentSize <= MaxChunkContentSize) { - Stage = EParseStage::ChunkData; - Line.Clear(); - } else { - // Invalid chunk content length - Stage = EParseStage::Error; - } - } else { - // Invalid chunk length - Stage = EParseStage::Error; - } - } else { - // Invalid body encoding - Stage = EParseStage::Error; - } - } - break; - } - case EParseStage::ChunkData: { - if (!IsError()) { - if (ProcessData(Content, data, ContentSize)) { - if (ProcessData(Line, data, 2)) { - if (Line == "\r\n") { - if (ChunkLength == 0) { - Body = Content; - Stage = EParseStage::Done; - } else { - Stage = EParseStage::ChunkLength; - } - Line.Clear(); - } else { - // Invalid body encoding - Stage = EParseStage::Error; - } - } - } - } - break; - } - - case EParseStage::Done: - case EParseStage::Error: { - data.Clear(); - break; - } - default: - Y_ABORT("Invalid processing sequence"); - break; - } - } - TSocketBuffer::Advance(len); -} - -template <> -THttpParser<THttpRequest, TSocketBuffer>::EParseStage THttpParser<THttpRequest, TSocketBuffer>::GetInitialStage() { - return EParseStage::Method; -} - -template <> -bool THttpParser<THttpResponse, TSocketBuffer>::HaveBody() const { - if (!Body.empty()) { - return true; - } - return (!Status.starts_with("1") && Status != "204" && Status != "304") - && (!ContentType.empty() || !ContentLength.empty() || !TransferEncoding.empty()); -} - -template <> -THttpParser<THttpResponse, TSocketBuffer>::EParseStage THttpParser<THttpResponse, TSocketBuffer>::GetInitialStage() { - return EParseStage::Protocol; -} - -void THttpResponse::Clear() { - // a dirty little trick - this->~THttpResponse(); // basically, do nothing - new (this) THttpResponse(); // reset all fields -} - -template <> -void THttpParser<THttpResponse, TSocketBuffer>::Advance(size_t len) { - TStringBuf data(Pos(), len); - while (!data.empty()) { - if (Stage != EParseStage::Error) { - LastSuccessStage = Stage; - } - switch (Stage) { - case EParseStage::Protocol: { - if (ProcessData(Protocol, data, '/', MaxProtocolSize)) { - Stage = EParseStage::Version; - } - break; - } - case EParseStage::Version: { - if (ProcessData(Version, data, ' ', MaxVersionSize)) { - Stage = EParseStage::Status; - } - break; - } - case EParseStage::Status: { - if (ProcessData(Status, data, ' ', MaxStatusSize)) { - Stage = EParseStage::Message; - } - break; - } - case EParseStage::Message: { - if (ProcessData(Message, data, "\r\n", MaxMessageSize)) { - Stage = EParseStage::Header; - Headers = TStringBuf(data.data(), size_t(0)); - } - break; - } - case EParseStage::Header: { - if (ProcessData(Header, data, "\r\n", MaxHeaderSize)) { - if (Header.empty()) { - if (HaveBody() && (ContentLength.empty() || ContentLength != "0")) { - Stage = EParseStage::Body; - } else if (TotalSize.has_value() && !data.empty()) { - Stage = EParseStage::Body; - } else { - Stage = EParseStage::Done; - } - } else { - ProcessHeader(Header); - } - Headers = TStringBuf(Headers.data(), data.data() - Headers.data()); - } - if (Stage != EParseStage::Body) { - break; - } - [[fallthrough]]; - } - case EParseStage::Body: { - if (TEqNoCase()(TransferEncoding, "chunked")) { - Stage = EParseStage::ChunkLength; - } else if (!ContentLength.empty()) { - if (is_not_number(ContentLength)) { - // Invalid content length - Stage = EParseStage::Error; - } else if (ProcessData(Body, data, FromStringWithDefault(ContentLength, 0))) { - Stage = EParseStage::Done; - if (Body && ContentEncoding == "deflate") { - Content = DecompressDeflate(Body); - Body = Content; - } - } - } else if (TotalSize.has_value()) { - if (ProcessData(Content, data, GetBodySizeFromTotalSize())) { - Body = Content; - Stage = EParseStage::Done; - if (Body && ContentEncoding == "deflate") { - Content = DecompressDeflate(Body); - Body = Content; - } - } - } else { - // Invalid body encoding - Stage = EParseStage::Error; - } - break; - } - case EParseStage::ChunkLength: { - if (ProcessData(Line, data, "\r\n", MaxChunkLengthSize)) { - if (!Line.empty()) { - ChunkLength = ParseHex(Line); - if (ChunkLength <= MaxChunkSize) { - ContentSize = Content.size() + ChunkLength; - if (ContentSize <= MaxChunkContentSize) { - Stage = EParseStage::ChunkData; - Line.Clear(); - } else { - // Invalid chunk content length - Stage = EParseStage::Error; - } - } else { - // Invalid chunk length - Stage = EParseStage::Error; - } - } else { - // Invalid body encoding - Stage = EParseStage::Error; - } - } - break; - } - case EParseStage::ChunkData: { - if (!IsError()) { - if (ProcessData(Content, data, ContentSize)) { - if (ProcessData(Line, data, 2)) { - if (Line == "\r\n") { - if (ChunkLength == 0) { - Body = Content; - Stage = EParseStage::Done; - if (Body && ContentEncoding == "deflate") { - Content = DecompressDeflate(Body); - Body = Content; - } - } else { - Stage = EParseStage::ChunkLength; - } - Line.Clear(); - } else { - // Invalid body encoding - Stage = EParseStage::Error; - } - } - } - } - break; - } - case EParseStage::Done: - case EParseStage::Error: - data.Clear(); - break; - default: - // Invalid processing sequence - Stage = EParseStage::Error; - break; - } - } - TSocketBuffer::Advance(len); -} - -template <> -void THttpParser<THttpResponse, TSocketBuffer>::ConnectionClosed() { - if (Stage == EParseStage::Done) { - return; - } - if (Stage == EParseStage::Body) { - // ? - Stage = EParseStage::Done; - } else { - LastSuccessStage = Stage; - Stage = EParseStage::Error; - } -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponseString(TStringBuf data) { - THttpParser<THttpResponse, TSocketBuffer> parser(data); - THeadersBuilder headers(parser.Headers); - if (!Endpoint->WorkerName.empty()) { - headers.Set("X-Worker-Name", Endpoint->WorkerName); - } - THttpOutgoingResponsePtr response = new THttpOutgoingResponse(this); - response->InitResponse(parser.Protocol, parser.Version, parser.Status, parser.Message); - if (parser.HaveBody()) { - if (parser.ContentType && !Endpoint->CompressContentTypes.empty()) { - TStringBuf contentType = parser.ContentType.Before(';'); - Trim(contentType, ' '); - if (Count(Endpoint->CompressContentTypes, contentType) != 0) { - if (response->EnableCompression()) { - headers.Erase("Content-Length"); // we will need new length after compression - } - } - } - headers.Erase("Transfer-Encoding"); // we erase transfer-encoding because we convert body to content-length - response->Set(headers); - response->SetBody(parser.Body); - } else { - headers.Erase("Transfer-Encoding"); // we erase transfer-encoding because we convert body to content-length - response->Set(headers); - if (!response->ContentLength) { - response->Set<&THttpResponse::ContentLength>("0"); - } - } - return response; -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponseOK(TStringBuf body, TStringBuf contentType, TInstant lastModified) { - return CreateResponse("200", "OK", contentType, body, lastModified); -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponseBadRequest(TStringBuf html, TStringBuf contentType) { - if (html.empty() && IsError()) { - contentType = "text/plain"; - html = GetErrorText(); - } - return CreateResponse("400", "Bad Request", contentType, html); -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponseNotFound(TStringBuf html, TStringBuf contentType) { - return CreateResponse("404", "Not Found", contentType, html); -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponseServiceUnavailable(TStringBuf html, TStringBuf contentType) { - return CreateResponse("503", "Service Unavailable", contentType, html); -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponseGatewayTimeout(TStringBuf html, TStringBuf contentType) { - return CreateResponse("504", "Gateway Timeout", contentType, html); -} - -THttpIncomingResponse::THttpIncomingResponse(THttpOutgoingRequestPtr request) - : Request(request) -{} - -THttpOutgoingResponsePtr THttpIncomingRequest::ConstructResponse(TStringBuf status, TStringBuf message) { - TStringBuf version = Version; - if (version != "1.0" && version != "1.1") { - version = "1.1"; - } - THttpOutgoingResponsePtr response = new THttpOutgoingResponse(this, "HTTP", version, status, message); - return response; -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateIncompleteResponse(TStringBuf status, TStringBuf message, const THeaders& headers) { - THttpOutgoingResponsePtr response = ConstructResponse(status, message); - if (!headers.Has("Connection")) { - response->Set<&THttpResponse::Connection>(GetConnection()); - } - if (!headers.Has("X-Worker-Name")) { - if (!Endpoint->WorkerName.empty()) { - response->Set("X-Worker-Name", Endpoint->WorkerName); - } - } - response->Set(headers); - return response; -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateIncompleteResponse(TStringBuf status, TStringBuf message, const THeaders& headers, TStringBuf body) { - THttpOutgoingResponsePtr response = CreateIncompleteResponse(status, message, headers); - if (!response->ContentType.empty() && !body.empty()) { - if (!Endpoint->CompressContentTypes.empty()) { - TStringBuf contentType = response->ContentType.Before(';'); - Trim(contentType, ' '); - if (Count(Endpoint->CompressContentTypes, contentType) != 0) { - response->EnableCompression(); - } - } - } - return response; -} - -void THttpIncomingRequest::FinishResponse(THttpOutgoingResponsePtr& response, TStringBuf body) { - if (response->IsNeedBody() || !body.empty()) { - if (Method == "HEAD") { - response->Set<&THttpResponse::ContentLength>(ToString(body.size())); - } else { - response->SetBody(body); - } - } -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponse(TStringBuf status, TStringBuf message) { - THttpOutgoingResponsePtr response = CreateIncompleteResponse(status, message); - FinishResponse(response); - return response; -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponse(TStringBuf status, TStringBuf message, const THeaders& headers) { - THttpOutgoingResponsePtr response = CreateIncompleteResponse(status, message, headers); - FinishResponse(response); - return response; -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponse(TStringBuf status, TStringBuf message, const THeaders& headers, TStringBuf body) { - THttpOutgoingResponsePtr response = CreateIncompleteResponse(status, message, headers, body); - FinishResponse(response, body); - return response; -} - -THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponse(TStringBuf status, TStringBuf message, TStringBuf contentType, TStringBuf body, TInstant lastModified) { - NHttp::THeadersBuilder headers; - if (!contentType.empty() && !body.empty()) { - headers.Set("Content-Type", contentType); - } - if (lastModified) { - headers.Set("Last-Modified", lastModified.FormatGmTime("%a, %d %b %Y %H:%M:%S GMT")); - } - return CreateResponse(status, message, headers, body); -} - -THttpIncomingRequestPtr THttpIncomingRequest::Duplicate() { - THttpIncomingRequestPtr request = new THttpIncomingRequest(*this); - request->Reparse(); - request->Timer.Reset(); - return request; -} - -THttpIncomingResponsePtr THttpIncomingResponse::Duplicate(THttpOutgoingRequestPtr request) { - THttpIncomingResponsePtr response = new THttpIncomingResponse(*this); - response->Reparse(); - response->Request = request; - return response; -} - -THttpOutgoingResponsePtr THttpOutgoingResponse::Duplicate(THttpIncomingRequestPtr request) { - THeadersBuilder headers(Headers); - if (!request->Endpoint->WorkerName.empty()) { - headers.Set("X-Worker-Name", request->Endpoint->WorkerName); - } - THttpOutgoingResponsePtr response = new THttpOutgoingResponse(request); - response->InitResponse(Protocol, Version, Status, Message); - if (Body) { - if (ContentType && !request->Endpoint->CompressContentTypes.empty()) { - TStringBuf contentType = ContentType.Before(';'); - Trim(contentType, ' '); - if (Count(request->Endpoint->CompressContentTypes, contentType) != 0) { - if (response->EnableCompression()) { - headers.Erase("Content-Length"); // we will need new length after compression - } - } - } - response->Set(headers); - response->SetBody(Body); - } else { - response->Set(headers); - if (!response->ContentLength) { - response->Set<&THttpResponse::ContentLength>("0"); - } - } - return response; -} - - -THttpOutgoingResponsePtr THttpIncomingResponse::Reverse(THttpIncomingRequestPtr request) { - THttpOutgoingResponsePtr response = new THttpOutgoingResponse(request); - response->Assign(Data(), Size()); - response->Reparse(); - return response; -} - -THttpOutgoingRequest::THttpOutgoingRequest(TStringBuf method, TStringBuf scheme, TStringBuf host, TStringBuf uri, TStringBuf protocol, TStringBuf version) { - Secure = (scheme == "https"); - TString urie = UrlEscapeRet(uri); - InitRequest(method, urie, protocol, version); - if (host) { - Set<&THttpRequest::Host>(host); - } -} - -THttpOutgoingRequest::THttpOutgoingRequest(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version) { - TStringBuf scheme, host, uri; - if (!CrackURL(url, scheme, host, uri)) { - Y_ABORT("Invalid URL specified"); - } - if (!scheme.empty() && scheme != "http" && scheme != "https") { - Y_ABORT("Invalid URL specified"); - } - Secure = (scheme == "https"); - TString urie = UrlEscapeRet(uri); - InitRequest(method, urie, protocol, version); - if (host) { - Set<&THttpRequest::Host>(host); - } -} - -THttpOutgoingRequestPtr THttpOutgoingRequest::CreateRequestString(const TString& data) { - THttpOutgoingRequestPtr request = new THttpOutgoingRequest(); - request->Assign(data.data(), data.size()); - request->Reparse(); - return request; -} - -THttpOutgoingRequestPtr THttpOutgoingRequest::CreateRequestGet(TStringBuf url) { - return CreateRequest("GET", url); -} - -THttpOutgoingRequestPtr THttpOutgoingRequest::CreateRequestGet(TStringBuf host, TStringBuf uri) { - return CreateHttpRequest("GET", host, uri); -} - -THttpOutgoingRequestPtr THttpOutgoingRequest::CreateRequestPost(TStringBuf url, TStringBuf contentType, TStringBuf body) { - return CreateRequest("POST", url, contentType, body); -} - -THttpOutgoingRequestPtr THttpOutgoingRequest::CreateRequestPost(TStringBuf host, TStringBuf uri, TStringBuf contentType, TStringBuf body) { - return CreateHttpRequest("POST", host, uri, contentType, body); -} - -THttpOutgoingRequestPtr THttpOutgoingRequest::CreateRequest(TStringBuf method, TStringBuf url, TStringBuf contentType, TStringBuf body) { - THttpOutgoingRequestPtr request = new THttpOutgoingRequest(method, url, "HTTP", "1.1"); - request->Set<&THttpRequest::Accept>("*/*"); - if (!contentType.empty()) { - request->Set<&THttpRequest::ContentType>(contentType); - request->Set<&THttpRequest::Body>(body); - } - return request; -} - -THttpOutgoingRequestPtr THttpOutgoingRequest::CreateHttpRequest(TStringBuf method, TStringBuf host, TStringBuf uri, TStringBuf contentType, TStringBuf body) { - THttpOutgoingRequestPtr request = new THttpOutgoingRequest(method, "http", host, uri, "HTTP", "1.1"); - request->Set<&THttpRequest::Accept>("*/*"); - if (!contentType.empty()) { - request->Set<&THttpRequest::ContentType>(contentType); - request->Set<&THttpRequest::Body>(body); - } - return request; -} - -THttpOutgoingRequestPtr THttpOutgoingRequest::Duplicate() { - THttpOutgoingRequestPtr request = new THttpOutgoingRequest(*this); - request->Reparse(); - return request; -} - -THttpOutgoingResponse::THttpOutgoingResponse(THttpIncomingRequestPtr request) - : Request(request) -{} - -THttpOutgoingResponse::THttpOutgoingResponse(THttpIncomingRequestPtr request, TStringBuf protocol, TStringBuf version, TStringBuf status, TStringBuf message) - : Request(request) -{ - InitResponse(protocol, version, status, message); -} - -const size_t THttpConfig::BUFFER_MIN_STEP; -const TDuration THttpConfig::CONNECTION_TIMEOUT; - -TUrlParameters::TUrlParameters(TStringBuf url) { - TStringBuf base; - TStringBuf params; - if (url.TrySplit('?', base, params)) { - for (TStringBuf param = params.NextTok('&'); !param.empty(); param = params.NextTok('&')) { - TStringBuf name = param.NextTok('='); - Parameters[name] = param; - } - } -} - -TString TUrlParameters::operator [](TStringBuf name) const { - TString value(Get(name)); - CGIUnescape(value); - return value; -} - -bool TUrlParameters::Has(TStringBuf name) const { - return Parameters.count(name) != 0; -} - -TStringBuf TUrlParameters::Get(TStringBuf name) const { - auto it = Parameters.find(name); - if (it != Parameters.end()) { - return it->second; - } - return TStringBuf(); -} - -TString TUrlParameters::Render() const { - TStringBuilder parameters; - for (const std::pair<TStringBuf, TStringBuf> parameter : Parameters) { - if (parameters.empty()) { - parameters << '?'; - } else { - parameters << '&'; - } - parameters << parameter.first; - parameters << '='; - parameters << parameter.second; - } - return parameters; -} - -TCookies::TCookies(TStringBuf cookie) { - for (TStringBuf param = cookie.NextTok(';'); !param.empty(); param = cookie.NextTok(';')) { - param.SkipPrefix(" "); - TStringBuf name = param.NextTok('='); - Cookies[name] = param; - } -} - -TStringBuf TCookies::operator [](TStringBuf name) const { - return Get(name); -} - -bool TCookies::Has(TStringBuf name) const { - return Cookies.count(name) != 0; -} - -TStringBuf TCookies::Get(TStringBuf name) const { - auto it = Cookies.find(name); - if (it != Cookies.end()) { - return it->second; - } - return TStringBuf(); -} - -TString TCookies::Render() const { - TStringBuilder cookies; - for (const std::pair<TStringBuf, TStringBuf> cookie : Cookies) { - if (!cookies.empty()) { - cookies << ' '; - } - cookies << cookie.first; - cookies << '='; - cookies << cookie.second; - cookies << ';'; - } - return cookies; -} - -TCookiesBuilder::TCookiesBuilder() - :TCookies(TStringBuf()) -{} - -void TCookiesBuilder::Set(TStringBuf name, TStringBuf data) { - Data.emplace_back(name, data); - Cookies[Data.back().first] = Data.back().second; -} - -THeaders::THeaders(TStringBuf headers) { - Parse(headers); -} - -size_t THeaders::Parse(TStringBuf headers) { - auto start = headers.begin(); - for (TStringBuf param = headers.NextTok("\r\n"); !param.empty(); param = headers.NextTok("\r\n")) { - TStringBuf name = param.NextTok(":"); - param.SkipPrefix(" "); - Headers[name] = param; - } - return headers.begin() - start; -} - -const TStringBuf THeaders::operator [](TStringBuf name) const { - return Get(name); -} - -bool THeaders::Has(TStringBuf name) const { - return Headers.count(name) != 0; -} - -TStringBuf THeaders::Get(TStringBuf name) const { - auto it = Headers.find(name); - if (it != Headers.end()) { - return it->second; - } - return TStringBuf(); -} - -TString THeaders::Render() const { - TStringBuilder headers; - for (const std::pair<TStringBuf, TStringBuf> header : Headers) { - headers << header.first; - headers << ": "; - headers << header.second; - headers << "\r\n"; - } - return headers; -} - -THeadersBuilder::THeadersBuilder() - : THeaders(TStringBuf()) -{} - -THeadersBuilder::THeadersBuilder(TStringBuf headers) - : THeaders(headers) -{} - -THeadersBuilder::THeadersBuilder(const THeadersBuilder& builder) { - for (const auto& pr : builder.Headers) { - Set(pr.first, pr.second); - } -} - -void THeadersBuilder::Set(TStringBuf name, TStringBuf data) { - Data.emplace_back(name, data); - Headers[Data.back().first] = Data.back().second; -} - -void THeadersBuilder::Erase(TStringBuf name) { - Headers.erase(name); -} - -} diff --git a/library/cpp/actors/http/http.h b/library/cpp/actors/http/http.h deleted file mode 100644 index d96ab062e89..00000000000 --- a/library/cpp/actors/http/http.h +++ /dev/null @@ -1,877 +0,0 @@ -#pragma once -#include <util/datetime/base.h> -#include <util/string/builder.h> -#include <util/system/thread.h> -#include <util/system/hp_timer.h> -#include <util/generic/hash_set.h> -#include <util/generic/buffer.h> -#include <util/generic/intrlist.h> -#include "http_config.h" - -// TODO(xenoxeno): hide in implementation -template <typename Type> -struct THash<TIntrusivePtr<Type>> { - size_t operator ()(const TIntrusivePtr<Type>& ptr) const { return reinterpret_cast<size_t>(ptr.Get()); } -}; - -template<> -inline void Out<NHttp::THttpConfig::SocketAddressType>(IOutputStream& o, const NHttp::THttpConfig::SocketAddressType& x) { - o << x->ToString(); -} - -namespace NHttp { - -bool IsIPv6(const TString& host); -bool IsIPv4(const TString& host); -bool CrackURL(TStringBuf url, TStringBuf& scheme, TStringBuf& host, TStringBuf& uri); -void CrackAddress(const TString& address, TString& hostname, TIpPort& port); -void TrimBegin(TStringBuf& target, char delim); -void TrimEnd(TStringBuf& target, char delim); -void Trim(TStringBuf& target, char delim); -void TrimEnd(TString& target, char delim); -TString CompressDeflate(TStringBuf source); -TString DecompressDeflate(TStringBuf source); - -struct TLessNoCase { - bool operator()(TStringBuf l, TStringBuf r) const { - auto ll = l.length(); - auto rl = r.length(); - if (ll != rl) { - return ll < rl; - } - return strnicmp(l.data(), r.data(), ll) < 0; - } -}; - -struct TEqNoCase { - bool operator()(TStringBuf l, TStringBuf r) const { - auto ll = l.length(); - auto rl = r.length(); - if (ll != rl) { - return false; - } - return strnicmp(l.data(), r.data(), ll) == 0; - } -}; - -struct TSensors { - TString Direction; - TString Host; - TString Url; - TString Status; - TDuration Time; - - TSensors( - TStringBuf direction, - TStringBuf host, - TStringBuf url, - TStringBuf status, - TDuration time) - : Direction(direction) - , Host(host) - , Url(url) - , Status(status) - , Time(time) - {} -}; - -struct TUrlParameters { - THashMap<TStringBuf, TStringBuf> Parameters; - - TUrlParameters(TStringBuf url); - TString operator [](TStringBuf name) const; - bool Has(TStringBuf name) const; - TStringBuf Get(TStringBuf name) const; // raw - TString Render() const; -}; - -struct TCookies { - THashMap<TStringBuf, TStringBuf> Cookies; - - TCookies(TStringBuf cookie); - TCookies(const TCookies&) = delete; - TStringBuf operator [](TStringBuf name) const; - bool Has(TStringBuf name) const; - TStringBuf Get(TStringBuf name) const; // raw - TString Render() const; -}; - -struct TCookiesBuilder : TCookies { - TDeque<std::pair<TString, TString>> Data; - - TCookiesBuilder(); - void Set(TStringBuf name, TStringBuf data); -}; - -struct THeaders { - TMap<TStringBuf, TStringBuf, TLessNoCase> Headers; - - THeaders() = default; - THeaders(TStringBuf headers); - THeaders(const THeaders&) = delete; - const TStringBuf operator [](TStringBuf name) const; - bool Has(TStringBuf name) const; - TStringBuf Get(TStringBuf name) const; // raw - size_t Parse(TStringBuf headers); - TString Render() const; -}; - -struct THeadersBuilder : THeaders { - TDeque<std::pair<TString, TString>> Data; - - THeadersBuilder(); - THeadersBuilder(TStringBuf headers); - THeadersBuilder(const THeadersBuilder& builder); - void Set(TStringBuf name, TStringBuf data); - void Erase(TStringBuf name); -}; - -class TSocketBuffer : public TBuffer, public THttpConfig { -public: - TSocketBuffer() - : TBuffer(BUFFER_SIZE) - {} - - bool EnsureEnoughSpaceAvailable(size_t need) { - size_t avail = Avail(); - if (avail < need) { - Reserve(Capacity() + std::max(need, BUFFER_MIN_STEP)); - return false; - } - return true; - } - - // non-destructive variant of AsString - TString AsString() const { - return TString(Data(), Size()); - } -}; - -class THttpRequest { -public: - TStringBuf Method; - TStringBuf URL; - TStringBuf Protocol; - TStringBuf Version; - TStringBuf Headers; - - TStringBuf Host; - TStringBuf Accept; - TStringBuf Connection; - TStringBuf ContentType; - TStringBuf ContentLength; - TStringBuf AcceptEncoding; - TStringBuf TransferEncoding; - - TStringBuf Body; - - static const TMap<TStringBuf, TStringBuf THttpRequest::*, TLessNoCase> HeadersLocation; - - template <TStringBuf THttpRequest::* Header> - static TStringBuf GetName(); - void Clear(); -}; - -class THttpResponse { -public: - TStringBuf Protocol; - TStringBuf Version; - TStringBuf Status; - TStringBuf Message; - TStringBuf Headers; - - TStringBuf Connection; - TStringBuf ContentType; - TStringBuf ContentLength; - TStringBuf TransferEncoding; - TStringBuf LastModified; - TStringBuf ContentEncoding; - - TStringBuf Body; - - static const TMap<TStringBuf, TStringBuf THttpResponse::*, TLessNoCase> HeadersLocation; - - template <TStringBuf THttpResponse::* Header> - static TStringBuf GetName(); - void Clear(); -}; - -template <typename HeaderType, typename BufferType> -class THttpParser : public HeaderType, public BufferType { -public: - enum class EParseStage : ui8 { - Method, - URL, - Protocol, - Version, - Status, - Message, - Header, - Body, - ChunkLength, - ChunkData, - Done, - Error, - }; - - static constexpr size_t MaxMethodSize = 8; - static constexpr size_t MaxURLSize = 2048; - static constexpr size_t MaxProtocolSize = 4; - static constexpr size_t MaxVersionSize = 4; - static constexpr size_t MaxStatusSize = 3; - static constexpr size_t MaxMessageSize = 1024; - static constexpr size_t MaxHeaderSize = 8192; - static constexpr size_t MaxChunkLengthSize = 8; - static constexpr size_t MaxChunkSize = 256 * 1024 * 1024; - static constexpr size_t MaxChunkContentSize = 1 * 1024 * 1024 * 1024; - - EParseStage Stage; - EParseStage LastSuccessStage; - TStringBuf Line; - TStringBuf& Header = Line; - size_t ChunkLength = 0; - size_t ContentSize = 0; - TString Content; // body storage - std::optional<size_t> TotalSize; - - THttpParser(const THttpParser& src) - : HeaderType(src) - , BufferType(src) - , Stage(src.Stage) - , LastSuccessStage(src.LastSuccessStage) - , Line() - , Header(Line) - , ChunkLength(src.ChunkLength) - , ContentSize(src.ContentSize) - , Content(src.Content) - {} - - template <typename StringType> - bool ProcessData(StringType& target, TStringBuf& source, char delim, size_t maxLen) { - TStringBuf maxSource(source.substr(0, maxLen + 1 - target.size())); - size_t pos = maxSource.find(delim); - target += maxSource.substr(0, pos); - source.Skip(pos); - if (target.size() > maxLen) { - Stage = EParseStage::Error; - return false; - } - if (!source.empty() && *source.begin() == delim) { - source.Skip(1); - } - return pos != TStringBuf::npos; - } - - template <typename StringType> - bool ProcessData(StringType& target, TStringBuf& source, TStringBuf delim, size_t maxLen) { - if (delim.empty()) { - return false; - } - if (delim.size() == 1) { - return ProcessData(target, source, delim[0], maxLen); - } - if (ProcessData(target, source, delim.back(), maxLen + 1)) { - for (signed i = delim.size() - 2; i >= 0; --i) { - TrimEnd(target, delim[i]); - } - return true; - } - return false; - } - - template <typename StringType> - bool ProcessData(StringType& target, TStringBuf& source, size_t size) { - TStringBuf maxSource(source.substr(0, size - target.size())); - target += maxSource; - source.Skip(maxSource.size()); - if (target.size() > size && !source.empty()) { - Stage = EParseStage::Error; - return false; - } - return target.size() == size; - } - - void ProcessHeader(TStringBuf& header) { - TStringBuf name = header.NextTok(':'); - TrimBegin(name, ' '); - TStringBuf value = header; - Trim(value, ' '); - auto cit = HeaderType::HeadersLocation.find(name); - if (cit != HeaderType::HeadersLocation.end()) { - this->*cit->second = value; - } - header.Clear(); - } - - size_t ParseHex(TStringBuf value) { - size_t result = 0; - for (char ch : value) { - if (ch >= '0' && ch <= '9') { - result *= 16; - result += ch - '0'; - } else if (ch >= 'a' && ch <= 'f') { - result *= 16; - result += 10 + ch - 'a'; - } else if (ch >= 'A' && ch <= 'F') { - result *= 16; - result += 10 + ch - 'A'; - } else if (ch == ';') { - break; - } else if (isspace(ch)) { - continue; - } else { - Stage = EParseStage::Error; - return 0; - } - } - return result; - } - - void Advance(size_t len); - void ConnectionClosed(); - - size_t GetBodySizeFromTotalSize() const { - return TotalSize.value() - (HeaderType::Headers.end() - BufferType::Data()); - } - - void Clear() { - BufferType::Clear(); - HeaderType::Clear(); - Stage = GetInitialStage(); - Line.Clear(); - Content.clear(); - } - - bool IsReady() const { - return Stage == EParseStage::Done; - } - - bool IsError() const { - return Stage == EParseStage::Error; - } - - TStringBuf GetErrorText() const { - switch (LastSuccessStage) { - case EParseStage::Method: - return "Invalid http method"; - case EParseStage::URL: - return "Invalid url"; - case EParseStage::Protocol: - return "Invalid http protocol"; - case EParseStage::Version: - return "Invalid http version"; - case EParseStage::Status: - return "Invalid http status"; - case EParseStage::Message: - return "Invalid http message"; - case EParseStage::Header: - return "Invalid http header"; - case EParseStage::Body: - return "Invalid content body"; - case EParseStage::ChunkLength: - case EParseStage::ChunkData: - return "Broken chunked data"; - case EParseStage::Done: - return "Everything is fine"; - case EParseStage::Error: - return "Error on error"; // wat? ...because we don't want to include default label here - } - } - - bool IsDone() const { - return IsReady() || IsError(); - } - - bool HaveBody() const; - - bool EnsureEnoughSpaceAvailable(size_t need = BufferType::BUFFER_MIN_STEP) { - bool result = BufferType::EnsureEnoughSpaceAvailable(need); - if (!result && !BufferType::Empty()) { - Reparse(); - } - return true; - } - - void Reparse() { - size_t size = BufferType::Size(); - Clear(); - Advance(size); - } - - TStringBuf GetRawData() const { - return TStringBuf(BufferType::Data(), BufferType::Size()); - } - - TString GetObfuscatedData() const { - THeaders headers(HeaderType::Headers); - TStringBuf authorization(headers["Authorization"]); - TStringBuf cookie(headers["Cookie"]); - TStringBuf x_ydb_auth_ticket(headers["x-ydb-auth-ticket"]); - TStringBuf x_yacloud_subjecttoken(headers["x-yacloud-subjecttoken"]); - TString data(GetRawData()); - if (!authorization.empty()) { - auto pos = data.find(authorization); - if (pos != TString::npos) { - data.replace(pos, authorization.size(), TString("<obfuscated>")); - } - } - if (!cookie.empty()) { - auto pos = data.find(cookie); - if (pos != TString::npos) { - data.replace(pos, cookie.size(), TString("<obfuscated>")); - } - } - if (!x_ydb_auth_ticket.empty()) { - auto pos = data.find(x_ydb_auth_ticket); - if (pos != TString::npos) { - data.replace(pos, x_ydb_auth_ticket.size(), TString("<obfuscated>")); - } - } - if (!x_yacloud_subjecttoken.empty()) { - auto pos = data.find(x_yacloud_subjecttoken); - if (pos != TString::npos) { - data.replace(pos, x_yacloud_subjecttoken.size(), TString("<obfuscated>")); - } - } - return data; - } - - static EParseStage GetInitialStage(); - - THttpParser() - : Stage(GetInitialStage()) - , LastSuccessStage(Stage) - {} - - THttpParser(TStringBuf data) - : Stage(GetInitialStage()) - , LastSuccessStage(Stage) - { - BufferType::Assign(data.data(), data.size()); - BufferType::Clear(); // reset position to 0 - TotalSize = data.size(); - Advance(data.size()); - } -}; - -template <typename HeaderType, typename BufferType> -class THttpRenderer : public HeaderType, public BufferType { -public: - enum class ERenderStage { - Init, - Header, - Body, - Done, - Error, - }; - - ERenderStage Stage = ERenderStage::Init; - TString Content; // body storage - - //THttpRenderer(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version); // request - void InitRequest(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version) { - Y_DEBUG_ABORT_UNLESS(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_DEBUG_ABORT_UNLESS(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()); - } - - void Append(char c) { - EnsureEnoughSpaceAvailable(sizeof(c)); - BufferType::Append(c); - } - - template <TStringBuf HeaderType::* string> - void AppendParsedValue(TStringBuf value) { - Append(value); - static_cast<HeaderType*>(this)->*string = TStringBuf(BufferType::Pos() - value.size(), value.size()); - } - - template <TStringBuf HeaderType::* name> - void Set(TStringBuf value) { - Y_DEBUG_ABORT_UNLESS(Stage == ERenderStage::Header); - Append(HeaderType::template GetName<name>()); - Append(": "); - AppendParsedValue<name>(value); - Append("\r\n"); - HeaderType::Headers = TStringBuf(HeaderType::Headers.Data(), BufferType::Pos() - HeaderType::Headers.Data()); - } - - void Set(TStringBuf name, TStringBuf value) { - Y_DEBUG_ABORT_UNLESS(Stage == ERenderStage::Header); - Append(name); - Append(": "); - auto data = BufferType::Pos(); - Append(value); - auto cit = HeaderType::HeadersLocation.find(name); - if (cit != HeaderType::HeadersLocation.end()) { - (this->*cit->second) = TStringBuf(data, BufferType::Pos()); - } - Append("\r\n"); - HeaderType::Headers = TStringBuf(HeaderType::Headers.Data(), BufferType::Pos() - HeaderType::Headers.Data()); - } - - void Set(const THeaders& headers) { - Y_DEBUG_ABORT_UNLESS(Stage == ERenderStage::Header); - for (const auto& [name, value] : headers.Headers) { - Set(name, value); - } - HeaderType::Headers = TStringBuf(HeaderType::Headers.Data(), BufferType::Pos() - HeaderType::Headers.Data()); - } - - static constexpr TStringBuf ALLOWED_CONTENT_ENCODINGS[] = {"deflate"}; - - void SetContentEncoding(TStringBuf contentEncoding) { - Y_DEBUG_ABORT_UNLESS(Stage == ERenderStage::Header); - if (Count(ALLOWED_CONTENT_ENCODINGS, contentEncoding) != 0) { - Set("Content-Encoding", contentEncoding); - } - } - - void FinishHeader() { - Append("\r\n"); - HeaderType::Headers = TStringBuf(HeaderType::Headers.Data(), BufferType::Pos() - HeaderType::Headers.Data()); - Stage = ERenderStage::Body; - } - - void SetBody(TStringBuf body) { - Y_DEBUG_ABORT_UNLESS(Stage == ERenderStage::Header); - if (HeaderType::ContentLength.empty()) { - Set<&HeaderType::ContentLength>(ToString(body.size())); - } - FinishHeader(); - AppendParsedValue<&HeaderType::Body>(body); - Stage = ERenderStage::Done; - } - - void FinishBody() { - Stage = ERenderStage::Done; - } - - bool IsDone() const { - return Stage == ERenderStage::Done; - } - - void Finish() { - switch (Stage) { - case ERenderStage::Header: - FinishHeader(); - FinishBody(); - break; - case ERenderStage::Body: - FinishBody(); - break; - default: - break; - } - } - - bool EnsureEnoughSpaceAvailable(size_t need = BufferType::BUFFER_MIN_STEP) { - bool result = BufferType::EnsureEnoughSpaceAvailable(need); - if (!result && !BufferType::Empty()) { - Reparse(); - } - return true; - } - - void Clear() { - BufferType::Clear(); - HeaderType::Clear(); - } - - void Reparse() { - // move-magic - size_t size = BufferType::Size(); - THttpParser<HeaderType, BufferType> parser; - // move the buffer to parser - static_cast<BufferType&>(parser) = std::move(static_cast<BufferType&>(*this)); - // reparse - parser.Clear(); - parser.Advance(size); - // move buffer and result back - bool needReassignBody = (parser.Body.data() == parser.Content.data()); - static_cast<HeaderType&>(*this) = std::move(static_cast<HeaderType&>(parser)); - static_cast<BufferType&>(*this) = std::move(static_cast<BufferType&>(parser)); - if (needReassignBody) { - Content = std::move(parser.Content); - HeaderType::Body = Content; - } - switch (parser.Stage) { - case THttpParser<HeaderType, BufferType>::EParseStage::Method: - case THttpParser<HeaderType, BufferType>::EParseStage::URL: - case THttpParser<HeaderType, BufferType>::EParseStage::Protocol: - case THttpParser<HeaderType, BufferType>::EParseStage::Version: - case THttpParser<HeaderType, BufferType>::EParseStage::Status: - case THttpParser<HeaderType, BufferType>::EParseStage::Message: - Stage = ERenderStage::Init; - break; - case THttpParser<HeaderType, BufferType>::EParseStage::Header: - Stage = ERenderStage::Header; - break; - case THttpParser<HeaderType, BufferType>::EParseStage::Body: - case THttpParser<HeaderType, BufferType>::EParseStage::ChunkLength: - case THttpParser<HeaderType, BufferType>::EParseStage::ChunkData: - Stage = ERenderStage::Body; - break; - case THttpParser<HeaderType, BufferType>::EParseStage::Done: - Stage = ERenderStage::Done; - break; - case THttpParser<HeaderType, BufferType>::EParseStage::Error: - Stage = ERenderStage::Error; - break; - } - Y_ABORT_UNLESS(size == BufferType::Size()); - } - - TStringBuf GetRawData() const { - return TStringBuf(BufferType::Data(), BufferType::Size()); - } -}; - -template <> -template <> -inline void THttpRenderer<THttpResponse, TSocketBuffer>::Set<&THttpResponse::Body>(TStringBuf value) { - SetBody(value); -} - -template <> -template <> -inline void THttpRenderer<THttpRequest, TSocketBuffer>::Set<&THttpRequest::Body>(TStringBuf value) { - SetBody(value); -} - -template <> -template <> -inline void THttpRenderer<THttpResponse, TSocketBuffer>::Set<&THttpResponse::ContentEncoding>(TStringBuf value) { - SetContentEncoding(value); -} - -struct THttpEndpointInfo { - TString WorkerName; - bool Secure = false; - const std::vector<TString> CompressContentTypes; // content types, which will be automatically compressed on response - - THttpEndpointInfo() = default; - -protected: - THttpEndpointInfo(std::vector<TString> compressContentTypes) - : CompressContentTypes(std::move(compressContentTypes)) - {} -}; - -class THttpIncomingRequest; -using THttpIncomingRequestPtr = TIntrusivePtr<THttpIncomingRequest>; - -class THttpOutgoingResponse; -using THttpOutgoingResponsePtr = TIntrusivePtr<THttpOutgoingResponse>; - -class THttpIncomingRequest : - public THttpParser<THttpRequest, TSocketBuffer>, - public TRefCounted<THttpIncomingRequest, TAtomicCounter> { -public: - std::shared_ptr<THttpEndpointInfo> Endpoint; - THttpConfig::SocketAddressType Address; - THPTimer Timer; - - THttpIncomingRequest() - : Endpoint(std::make_shared<THttpEndpointInfo>()) - {} - - THttpIncomingRequest(std::shared_ptr<THttpEndpointInfo> endpoint, const THttpConfig::SocketAddressType& address) - : Endpoint(std::move(endpoint)) - , Address(address) - {} - - THttpIncomingRequest(TStringBuf content, std::shared_ptr<THttpEndpointInfo> endpoint, const THttpConfig::SocketAddressType& address) - : THttpParser(content) - , Endpoint(std::move(endpoint)) - , Address(address) - {} - - bool IsConnectionClose() const { - if (Connection.empty()) { - return Version == "1.0"; - } else { - return TEqNoCase()(Connection, "close"); - } - } - - TStringBuf GetConnection() const { - if (!Connection.empty()) { - if (TEqNoCase()(Connection, "keep-alive")) { - return "keep-alive"; - } - if (TEqNoCase()(Connection, "close")) { - return "close"; - } - } - return Version == "1.0" ? "close" : "keep-alive"; - } - - THttpOutgoingResponsePtr CreateResponseOK(TStringBuf body, TStringBuf contentType = "text/html", TInstant lastModified = TInstant()); - THttpOutgoingResponsePtr CreateResponseString(TStringBuf data); - THttpOutgoingResponsePtr CreateResponseBadRequest(TStringBuf html = TStringBuf(), TStringBuf contentType = "text/html"); // 400 - THttpOutgoingResponsePtr CreateResponseNotFound(TStringBuf html = TStringBuf(), TStringBuf contentType = "text/html"); // 404 - THttpOutgoingResponsePtr CreateResponseServiceUnavailable(TStringBuf html = TStringBuf(), TStringBuf contentType = "text/html"); // 503 - THttpOutgoingResponsePtr CreateResponseGatewayTimeout(TStringBuf html = TStringBuf(), TStringBuf contentType = "text/html"); // 504 - THttpOutgoingResponsePtr CreateResponse(TStringBuf status, TStringBuf message); - THttpOutgoingResponsePtr CreateResponse(TStringBuf status, TStringBuf message, const THeaders& headers); - THttpOutgoingResponsePtr CreateResponse(TStringBuf status, TStringBuf message, const THeaders& headers, TStringBuf body); - THttpOutgoingResponsePtr CreateResponse( - TStringBuf status, - TStringBuf message, - TStringBuf contentType, - TStringBuf body = TStringBuf(), - TInstant lastModified = TInstant()); - - THttpOutgoingResponsePtr CreateIncompleteResponse(TStringBuf status, TStringBuf message, const THeaders& headers = {}); - THttpOutgoingResponsePtr CreateIncompleteResponse(TStringBuf status, TStringBuf message, const THeaders& headers, TStringBuf body); - - THttpIncomingRequestPtr Duplicate(); - -private: - THttpOutgoingResponsePtr ConstructResponse(TStringBuf status, TStringBuf message); - void FinishResponse(THttpOutgoingResponsePtr& response, TStringBuf body = TStringBuf()); -}; - -class THttpIncomingResponse; -using THttpIncomingResponsePtr = TIntrusivePtr<THttpIncomingResponse>; - -class THttpOutgoingRequest; -using THttpOutgoingRequestPtr = TIntrusivePtr<THttpOutgoingRequest>; - -class THttpIncomingResponse : - public THttpParser<THttpResponse, TSocketBuffer>, - public TRefCounted<THttpIncomingResponse, TAtomicCounter> { -public: - THttpIncomingResponse(THttpOutgoingRequestPtr request); - - THttpOutgoingRequestPtr GetRequest() const { - return Request; - } - - THttpIncomingResponsePtr Duplicate(THttpOutgoingRequestPtr request); - THttpOutgoingResponsePtr Reverse(THttpIncomingRequestPtr request); - -protected: - THttpOutgoingRequestPtr Request; -}; - -class THttpOutgoingRequest : - public THttpRenderer<THttpRequest, TSocketBuffer>, - public TRefCounted<THttpOutgoingRequest, TAtomicCounter> { -public: - THPTimer Timer; - bool Secure = false; - - THttpOutgoingRequest() = default; - THttpOutgoingRequest(TStringBuf method, TStringBuf url, TStringBuf protocol, TStringBuf version); - THttpOutgoingRequest(TStringBuf method, TStringBuf scheme, TStringBuf host, TStringBuf uri, TStringBuf protocol, TStringBuf version); - static THttpOutgoingRequestPtr CreateRequestString(TStringBuf data); - static THttpOutgoingRequestPtr CreateRequestString(const TString& data); - static THttpOutgoingRequestPtr CreateRequestGet(TStringBuf url); - static THttpOutgoingRequestPtr CreateRequestGet(TStringBuf host, TStringBuf uri); // http only - static THttpOutgoingRequestPtr CreateRequestPost(TStringBuf url, TStringBuf contentType = {}, TStringBuf body = {}); - static THttpOutgoingRequestPtr CreateRequestPost(TStringBuf host, TStringBuf uri, TStringBuf contentType, TStringBuf body); // http only - static THttpOutgoingRequestPtr CreateRequest(TStringBuf method, TStringBuf url, TStringBuf contentType = TStringBuf(), TStringBuf body = TStringBuf()); - static THttpOutgoingRequestPtr CreateHttpRequest(TStringBuf method, TStringBuf host, TStringBuf uri, TStringBuf contentType = TStringBuf(), TStringBuf body = TStringBuf()); - THttpOutgoingRequestPtr Duplicate(); -}; - -class THttpOutgoingResponse : - public THttpRenderer<THttpResponse, TSocketBuffer>, - public TRefCounted<THttpOutgoingResponse, TAtomicCounter> { -public: - THttpOutgoingResponse(THttpIncomingRequestPtr request); - THttpOutgoingResponse(THttpIncomingRequestPtr request, TStringBuf protocol, TStringBuf version, TStringBuf status, TStringBuf message); - - bool IsConnectionClose() const { - if (!Connection.empty()) { - return TEqNoCase()(Connection, "close"); - } else { - return Request->IsConnectionClose(); - } - } - - bool IsNeedBody() const { - return GetRequest()->Method != "HEAD" && Status != "204"; - } - - bool 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()); - return true; - } - return false; - } - - void SetBody(TStringBuf body) { - if (ContentEncoding == "deflate") { - TString compressedBody = CompressDeflate(body); - THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(compressedBody); - Body = Content = body; - } else { - THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(body); - } - } - - void SetBody(const TString& body) { - if (ContentEncoding == "deflate") { - TString compressedBody = CompressDeflate(body); - THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(compressedBody); - Body = Content = body; - } else { - THttpRenderer<THttpResponse, TSocketBuffer>::SetBody(body); - } - } - - THttpIncomingRequestPtr GetRequest() const { - return Request; - } - - THttpOutgoingResponsePtr Duplicate(THttpIncomingRequestPtr request); - -// it's temporary accessible for cleanup -//protected: - THttpIncomingRequestPtr Request; - std::unique_ptr<TSensors> Sensors; -}; - -} diff --git a/library/cpp/actors/http/http_cache.cpp b/library/cpp/actors/http/http_cache.cpp deleted file mode 100644 index d2856f70c22..00000000000 --- a/library/cpp/actors/http/http_cache.cpp +++ /dev/null @@ -1,608 +0,0 @@ -#include "http.h" -#include "http_proxy.h" -#include "http_cache.h" -#include <library/cpp/actors/core/actor_bootstrapped.h> -#include <library/cpp/actors/core/executor_pool_basic.h> -#include <library/cpp/actors/core/log.h> -#include <library/cpp/actors/core/scheduler_basic.h> -#include <library/cpp/actors/http/http.h> -#include <library/cpp/digest/md5/md5.h> -#include <util/digest/multi.h> -#include <util/generic/queue.h> -#include <util/string/cast.h> - -namespace NHttp { - -static bool StatusSuccess(const TStringBuf& status) { - return status.StartsWith("2"); -} - -class THttpOutgoingCacheActor : public NActors::TActorBootstrapped<THttpOutgoingCacheActor>, THttpConfig { -public: - using TBase = NActors::TActorBootstrapped<THttpOutgoingCacheActor>; - NActors::TActorId HttpProxyId; - TGetCachePolicy GetCachePolicy; - static constexpr TDuration RefreshTimeout = TDuration::Seconds(1); - - struct TCacheKey { - TString Host; - TString URL; - TString Headers; - - operator size_t() const { - return MultiHash(Host, URL, Headers); - } - - TString GetId() const { - return MD5::Calc(Host + ':' + URL + ':' + Headers); - } - }; - - struct TCacheRecord { - TInstant RefreshTime; - TInstant DeathTime; - TCachePolicy CachePolicy; - NHttp::THttpOutgoingRequestPtr Request; - NHttp::THttpOutgoingRequestPtr OutgoingRequest; - TDuration Timeout; - NHttp::THttpIncomingResponsePtr Response; - TString Error; - TVector<NHttp::TEvHttpProxy::TEvHttpOutgoingRequest::TPtr> Waiters; - - TCacheRecord(const TCachePolicy cachePolicy) - : CachePolicy(cachePolicy) - {} - - bool IsValid() const { - return Response != nullptr || !Error.empty(); - } - - void UpdateResponse(NHttp::THttpIncomingResponsePtr response, const TString& error, TInstant now) { - if (error.empty() || Response == nullptr || !CachePolicy.KeepOnError) { - Response = response; - Error = error; - } - RefreshTime = now + CachePolicy.TimeToRefresh; - if (CachePolicy.PaceToRefresh) { - RefreshTime += TDuration::MilliSeconds(RandomNumber<ui64>() % CachePolicy.PaceToRefresh.MilliSeconds()); - } - } - - TString GetName() const { - return TStringBuilder() << (Request->Secure ? "https://" : "http://") << Request->Host << Request->URL; - } - }; - - struct TRefreshRecord { - TCacheKey Key; - TInstant RefreshTime; - - bool operator <(const TRefreshRecord& b) const { - return RefreshTime > b.RefreshTime; - } - }; - - THashMap<TCacheKey, TCacheRecord> Cache; - TPriorityQueue<TRefreshRecord> RefreshQueue; - THashMap<THttpOutgoingRequest*, TCacheKey> OutgoingRequests; - - THttpOutgoingCacheActor(const NActors::TActorId& httpProxyId, TGetCachePolicy getCachePolicy) - : HttpProxyId(httpProxyId) - , GetCachePolicy(std::move(getCachePolicy)) - {} - - static constexpr char ActorName[] = "HTTP_OUT_CACHE_ACTOR"; - - void Bootstrap(const NActors::TActorContext&) { - // - Become(&THttpOutgoingCacheActor::StateWork, RefreshTimeout, new NActors::TEvents::TEvWakeup()); - } - - static TString GetCacheHeadersKey(const NHttp::THttpOutgoingRequest* request, const TCachePolicy& policy) { - TStringBuilder key; - if (!policy.HeadersToCacheKey.empty()) { - NHttp::THeaders headers(request->Headers); - for (const TString& header : policy.HeadersToCacheKey) { - key << headers[header]; - } - } - return key; - } - - static TCacheKey GetCacheKey(const NHttp::THttpOutgoingRequest* request, const TCachePolicy& policy) { - return { ToString(request->Host), ToString(request->URL), GetCacheHeadersKey(request, policy) }; - } - - void Handle(NHttp::TEvHttpProxy::TEvHttpOutgoingResponse::TPtr event, const NActors::TActorContext& ctx) { - ctx.Send(event->Forward(HttpProxyId)); - } - - void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) { - ctx.Send(event->Forward(HttpProxyId)); - } - - void Handle(NHttp::TEvHttpProxy::TEvAddListeningPort::TPtr event, const NActors::TActorContext& ctx) { - ctx.Send(event->Forward(HttpProxyId)); - } - - void Handle(NHttp::TEvHttpProxy::TEvRegisterHandler::TPtr event, const NActors::TActorContext& ctx) { - ctx.Send(event->Forward(HttpProxyId)); - } - - void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr event, const NActors::TActorContext& ctx) { - NHttp::THttpOutgoingRequestPtr request(event->Get()->Request); - NHttp::THttpIncomingResponsePtr response(event->Get()->Response); - auto itRequests = OutgoingRequests.find(request.Get()); - if (itRequests == OutgoingRequests.end()) { - LOG_ERROR_S(ctx, HttpLog, "Cache received response to unknown request " << request->Host << request->URL); - return; - } - auto key = itRequests->second; - OutgoingRequests.erase(itRequests); - auto it = Cache.find(key); - if (it == Cache.end()) { - LOG_ERROR_S(ctx, HttpLog, "Cache received response to unknown cache key " << request->Host << request->URL); - return; - } - TCacheRecord& cacheRecord = it->second; - cacheRecord.OutgoingRequest.Reset(); - for (auto& waiter : cacheRecord.Waiters) { - NHttp::THttpIncomingResponsePtr response2; - TString error2; - if (response != nullptr) { - response2 = response->Duplicate(waiter->Get()->Request); - } - if (!event->Get()->Error.empty()) { - error2 = event->Get()->Error; - } - ctx.Send(waiter->Sender, new NHttp::TEvHttpProxy::TEvHttpIncomingResponse(waiter->Get()->Request, response2, error2)); - } - cacheRecord.Waiters.clear(); - TString error; - if (event->Get()->Error.empty()) { - if (event->Get()->Response != nullptr && !StatusSuccess(event->Get()->Response->Status)) { - error = event->Get()->Response->Message; - } - } else { - error = event->Get()->Error; - } - if (!error.empty()) { - LOG_WARN_S(ctx, HttpLog, "Error from " << cacheRecord.GetName() << ": " << error); - } - LOG_DEBUG_S(ctx, HttpLog, "OutgoingUpdate " << cacheRecord.GetName()); - cacheRecord.UpdateResponse(response, event->Get()->Error, ctx.Now()); - RefreshQueue.push({it->first, it->second.RefreshTime}); - LOG_DEBUG_S(ctx, HttpLog, "OutgoingSchedule " << cacheRecord.GetName() << " at " << cacheRecord.RefreshTime << " until " << cacheRecord.DeathTime); - } - - void Handle(NHttp::TEvHttpProxy::TEvHttpOutgoingRequest::TPtr event, const NActors::TActorContext& ctx) { - const NHttp::THttpOutgoingRequest* request = event->Get()->Request.Get(); - auto policy = GetCachePolicy(request); - if (policy.TimeToExpire == TDuration()) { - ctx.Send(event->Forward(HttpProxyId)); - return; - } - auto key = GetCacheKey(request, policy); - auto it = Cache.find(key); - if (it != Cache.end()) { - if (it->second.IsValid()) { - LOG_DEBUG_S(ctx, HttpLog, "OutgoingRespond " - << it->second.GetName() - << " (" - << ((it->second.Response != nullptr) ? ToString(it->second.Response->Size()) : TString("error")) - << ")"); - NHttp::THttpIncomingResponsePtr response = it->second.Response; - if (response != nullptr) { - response = response->Duplicate(event->Get()->Request); - } - ctx.Send(event->Sender, - new NHttp::TEvHttpProxy::TEvHttpIncomingResponse(event->Get()->Request, - response, - it->second.Error)); - it->second.DeathTime = ctx.Now() + it->second.CachePolicy.TimeToExpire; // prolong active cache items - return; - } - } else { - it = Cache.emplace(key, policy).first; - it->second.Request = event->Get()->Request; - it->second.Timeout = event->Get()->Timeout; - it->second.OutgoingRequest = it->second.Request->Duplicate(); - OutgoingRequests[it->second.OutgoingRequest.Get()] = key; - LOG_DEBUG_S(ctx, HttpLog, "OutgoingInitiate " << it->second.GetName()); - ctx.Send(HttpProxyId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest(it->second.OutgoingRequest, it->second.Timeout)); - } - it->second.DeathTime = ctx.Now() + it->second.CachePolicy.TimeToExpire; - it->second.Waiters.emplace_back(std::move(event)); - } - - void HandleRefresh(const NActors::TActorContext& ctx) { - while (!RefreshQueue.empty() && RefreshQueue.top().RefreshTime <= ctx.Now()) { - TRefreshRecord rrec = RefreshQueue.top(); - RefreshQueue.pop(); - auto it = Cache.find(rrec.Key); - if (it != Cache.end()) { - if (it->second.DeathTime > ctx.Now()) { - LOG_DEBUG_S(ctx, HttpLog, "OutgoingRefresh " << it->second.GetName()); - it->second.OutgoingRequest = it->second.Request->Duplicate(); - OutgoingRequests[it->second.OutgoingRequest.Get()] = it->first; - ctx.Send(HttpProxyId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest(it->second.OutgoingRequest, it->second.Timeout)); - } else { - LOG_DEBUG_S(ctx, HttpLog, "OutgoingForget " << it->second.GetName()); - if (it->second.OutgoingRequest) { - OutgoingRequests.erase(it->second.OutgoingRequest.Get()); - } - Cache.erase(it); - } - } - } - ctx.Schedule(RefreshTimeout, new NActors::TEvents::TEvWakeup()); - } - - STFUNC(StateWork) { - switch (ev->GetTypeRewrite()) { - HFunc(NHttp::TEvHttpProxy::TEvHttpIncomingResponse, Handle); - HFunc(NHttp::TEvHttpProxy::TEvHttpOutgoingRequest, Handle); - HFunc(NHttp::TEvHttpProxy::TEvAddListeningPort, Handle); - HFunc(NHttp::TEvHttpProxy::TEvRegisterHandler, Handle); - HFunc(NHttp::TEvHttpProxy::TEvHttpIncomingRequest, Handle); - HFunc(NHttp::TEvHttpProxy::TEvHttpOutgoingResponse, Handle); - CFunc(NActors::TEvents::TSystem::Wakeup, HandleRefresh); - } - } -}; - -const TDuration THttpOutgoingCacheActor::RefreshTimeout; - -class THttpIncomingCacheActor : public NActors::TActorBootstrapped<THttpIncomingCacheActor>, THttpConfig { -public: - using TBase = NActors::TActorBootstrapped<THttpIncomingCacheActor>; - NActors::TActorId HttpProxyId; - TGetCachePolicy GetCachePolicy; - static constexpr TDuration RefreshTimeout = TDuration::Seconds(1); - THashMap<TString, TActorId> Handlers; - - struct TCacheKey { - TString Host; - TString URL; - TString Headers; - - operator size_t() const { - return MultiHash(Host, URL, Headers); - } - - TString GetId() const { - return MD5::Calc(Host + ':' + URL + ':' + Headers); - } - }; - - struct TCacheRecord { - TInstant RefreshTime; - TInstant DeathTime; - TCachePolicy CachePolicy; - TString CacheId; - NHttp::THttpIncomingRequestPtr Request; - TDuration Timeout; - NHttp::THttpOutgoingResponsePtr Response; - TVector<NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr> Waiters; - ui32 Retries = 0; - bool Enqueued = false; - - TCacheRecord(const TCachePolicy cachePolicy) - : CachePolicy(cachePolicy) - {} - - bool IsValid() const { - return Response != nullptr; - } - - void InitRequest(NHttp::THttpIncomingRequestPtr request) { - Request = request; - if (CachePolicy.TimeToExpire) { - DeathTime = NActors::TlsActivationContext->Now() + CachePolicy.TimeToExpire; - } - } - - void UpdateResponse(NHttp::THttpOutgoingResponsePtr response, const TString& error, TInstant now) { - if (error.empty() || !CachePolicy.KeepOnError) { - Response = response; - } - Retries = 0; - if (CachePolicy.TimeToRefresh) { - RefreshTime = now + CachePolicy.TimeToRefresh; - if (CachePolicy.PaceToRefresh) { - RefreshTime += TDuration::MilliSeconds(RandomNumber<ui64>() % CachePolicy.PaceToRefresh.MilliSeconds()); - } - } - } - - void UpdateExpireTime() { - if (CachePolicy.TimeToExpire) { - DeathTime = NActors::TlsActivationContext->Now() + CachePolicy.TimeToExpire; - } - } - - TString GetName() const { - return TStringBuilder() << (Request->Endpoint->Secure ? "https://" : "http://") << Request->Host << Request->URL - << " (" << CacheId << ")"; - } - }; - - struct TRefreshRecord { - TCacheKey Key; - TInstant RefreshTime; - - bool operator <(const TRefreshRecord& b) const { - return RefreshTime > b.RefreshTime; - } - }; - - THashMap<TCacheKey, TCacheRecord> Cache; - TPriorityQueue<TRefreshRecord> RefreshQueue; - THashMap<THttpIncomingRequest*, TCacheKey> IncomingRequests; - - THttpIncomingCacheActor(const NActors::TActorId& httpProxyId, TGetCachePolicy getCachePolicy) - : HttpProxyId(httpProxyId) - , GetCachePolicy(std::move(getCachePolicy)) - {} - - static constexpr char ActorName[] = "HTTP_IN_CACHE_ACTOR"; - - void Bootstrap(const NActors::TActorContext&) { - // - Become(&THttpIncomingCacheActor::StateWork, RefreshTimeout, new NActors::TEvents::TEvWakeup()); - } - - static TString GetCacheHeadersKey(const NHttp::THttpIncomingRequest* request, const TCachePolicy& policy) { - TStringBuilder key; - if (!policy.HeadersToCacheKey.empty()) { - NHttp::THeaders headers(request->Headers); - for (const TString& header : policy.HeadersToCacheKey) { - key << headers[header]; - } - } - return key; - } - - static TCacheKey GetCacheKey(const NHttp::THttpIncomingRequest* request, const TCachePolicy& policy) { - return { ToString(request->Host), ToString(request->URL), GetCacheHeadersKey(request, policy) }; - } - - TActorId GetRequestHandler(NHttp::THttpIncomingRequestPtr request) { - TStringBuf url = request->URL.Before('?'); - THashMap<TString, TActorId>::iterator it; - while (!url.empty()) { - it = Handlers.find(url); - if (it != Handlers.end()) { - return it->second; - } else { - if (url.EndsWith('/')) { - url.Trunc(url.size() - 1); - } - size_t pos = url.rfind('/'); - if (pos == TStringBuf::npos) { - break; - } else { - url = url.substr(0, pos + 1); - } - } - } - return {}; - } - - void SendCacheRequest(const TCacheKey& cacheKey, TCacheRecord& cacheRecord, const NActors::TActorContext& ctx) { - cacheRecord.Request = cacheRecord.Request->Duplicate(); - cacheRecord.Request->AcceptEncoding.Clear(); // disable compression - IncomingRequests[cacheRecord.Request.Get()] = cacheKey; - TActorId handler = GetRequestHandler(cacheRecord.Request); - if (handler) { - Send(handler, new NHttp::TEvHttpProxy::TEvHttpIncomingRequest(cacheRecord.Request)); - } else { - LOG_ERROR_S(ctx, HttpLog, "Can't find cache handler for " << cacheRecord.GetName()); - } - } - - void DropCacheRecord(THashMap<TCacheKey, TCacheRecord>::iterator it) { - if (it->second.Request) { - IncomingRequests.erase(it->second.Request.Get()); - } - for (auto& waiter : it->second.Waiters) { - NHttp::THttpOutgoingResponsePtr response; - response = waiter->Get()->Request->CreateResponseGatewayTimeout("Timeout", "text/plain"); - Send(waiter->Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(response)); - } - Cache.erase(it); - } - - void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingResponse::TPtr event, const NActors::TActorContext& ctx) { - ctx.Send(event->Forward(HttpProxyId)); - } - - void Handle(NHttp::TEvHttpProxy::TEvHttpOutgoingRequest::TPtr event, const NActors::TActorContext& ctx) { - ctx.Send(event->Forward(HttpProxyId)); - } - - void Handle(NHttp::TEvHttpProxy::TEvAddListeningPort::TPtr event, const NActors::TActorContext& ctx) { - ctx.Send(event->Forward(HttpProxyId)); - } - - void Handle(NHttp::TEvHttpProxy::TEvRegisterHandler::TPtr event, const NActors::TActorContext& ctx) { - Handlers[event->Get()->Path] = event->Get()->Handler; - ctx.Send(HttpProxyId, new NHttp::TEvHttpProxy::TEvRegisterHandler(event->Get()->Path, ctx.SelfID)); - } - - void Handle(NHttp::TEvHttpProxy::TEvHttpOutgoingResponse::TPtr event, const NActors::TActorContext& ctx) { - NHttp::THttpIncomingRequestPtr request(event->Get()->Response->GetRequest()); - NHttp::THttpOutgoingResponsePtr response(event->Get()->Response); - auto itRequests = IncomingRequests.find(request.Get()); - if (itRequests == IncomingRequests.end()) { - LOG_ERROR_S(ctx, HttpLog, "Cache received response to unknown request " << request->Host << request->URL); - return; - } - - TCacheKey key = itRequests->second; - auto it = Cache.find(key); - if (it == Cache.end()) { - LOG_ERROR_S(ctx, HttpLog, "Cache received response to unknown cache key " << request->Host << request->URL); - return; - } - - IncomingRequests.erase(itRequests); - TCacheRecord& cacheRecord = it->second; - TStringBuf status; - TString error; - - if (event->Get()->Response != nullptr) { - status = event->Get()->Response->Status; - if (!StatusSuccess(status)) { - error = event->Get()->Response->Message; - } - } - if (cacheRecord.CachePolicy.RetriesCount > 0) { - auto itStatusToRetry = std::find(cacheRecord.CachePolicy.StatusesToRetry.begin(), cacheRecord.CachePolicy.StatusesToRetry.end(), status); - if (itStatusToRetry != cacheRecord.CachePolicy.StatusesToRetry.end()) { - if (cacheRecord.Retries < cacheRecord.CachePolicy.RetriesCount) { - ++cacheRecord.Retries; - LOG_WARN_S(ctx, HttpLog, "IncomingRetry " << cacheRecord.GetName() << ": " << status << " " << error); - SendCacheRequest(key, cacheRecord, ctx); - return; - } - } - } - for (auto& waiter : cacheRecord.Waiters) { - NHttp::THttpOutgoingResponsePtr response2; - response2 = response->Duplicate(waiter->Get()->Request); - ctx.Send(waiter->Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(response2)); - } - cacheRecord.Waiters.clear(); - if (!error.empty()) { - LOG_WARN_S(ctx, HttpLog, "Error from " << cacheRecord.GetName() << ": " << error); - if (!cacheRecord.Response) { - LOG_DEBUG_S(ctx, HttpLog, "IncomingDiscard " << cacheRecord.GetName()); - DropCacheRecord(it); - return; - } - } - if (cacheRecord.CachePolicy.TimeToRefresh) { - LOG_DEBUG_S(ctx, HttpLog, "IncomingUpdate " << cacheRecord.GetName()); - cacheRecord.UpdateResponse(response, error, ctx.Now()); - if (!cacheRecord.Enqueued) { - RefreshQueue.push({it->first, it->second.RefreshTime}); - cacheRecord.Enqueued = true; - } - LOG_DEBUG_S(ctx, HttpLog, "IncomingSchedule " << cacheRecord.GetName() << " at " << cacheRecord.RefreshTime << " until " << cacheRecord.DeathTime); - } else { - LOG_DEBUG_S(ctx, HttpLog, "IncomingDrop " << cacheRecord.GetName()); - DropCacheRecord(it); - } - } - - void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) { - const NHttp::THttpIncomingRequest* request = event->Get()->Request.Get(); - TCachePolicy policy = GetCachePolicy(request); - if (policy.TimeToExpire == TDuration() && policy.RetriesCount == 0) { - TActorId handler = GetRequestHandler(event->Get()->Request); - if (handler) { - ctx.Send(event->Forward(handler)); - } - return; - } - auto key = GetCacheKey(request, policy); - auto it = Cache.find(key); - if (it != Cache.end() && !policy.DiscardCache) { - it->second.UpdateExpireTime(); - if (it->second.IsValid()) { - LOG_DEBUG_S(ctx, HttpLog, "IncomingRespond " - << it->second.GetName() - << " (" - << ((it->second.Response != nullptr) ? ToString(it->second.Response->Size()) : TString("error")) - << ")"); - NHttp::THttpOutgoingResponsePtr response = it->second.Response; - if (response != nullptr) { - response = response->Duplicate(event->Get()->Request); - } - ctx.Send(event->Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(response)); - return; - } - } else { - it = Cache.emplace(key, policy).first; - it->second.CacheId = key.GetId(); // for debugging - it->second.InitRequest(event->Get()->Request); - if (policy.DiscardCache) { - LOG_DEBUG_S(ctx, HttpLog, "IncomingDiscardCache " << it->second.GetName()); - } - LOG_DEBUG_S(ctx, HttpLog, "IncomingInitiate " << it->second.GetName()); - SendCacheRequest(key, it->second, ctx); - } - it->second.Waiters.emplace_back(std::move(event)); - } - - void HandleRefresh(const NActors::TActorContext& ctx) { - while (!RefreshQueue.empty() && RefreshQueue.top().RefreshTime <= ctx.Now()) { - TRefreshRecord rrec = RefreshQueue.top(); - RefreshQueue.pop(); - auto it = Cache.find(rrec.Key); - if (it != Cache.end()) { - it->second.Enqueued = false; - if (it->second.DeathTime > ctx.Now()) { - LOG_DEBUG_S(ctx, HttpLog, "IncomingRefresh " << it->second.GetName()); - SendCacheRequest(it->first, it->second, ctx); - } else { - LOG_DEBUG_S(ctx, HttpLog, "IncomingForget " << it->second.GetName()); - DropCacheRecord(it); - } - } - } - ctx.Schedule(RefreshTimeout, new NActors::TEvents::TEvWakeup()); - } - - STFUNC(StateWork) { - switch (ev->GetTypeRewrite()) { - HFunc(NHttp::TEvHttpProxy::TEvHttpIncomingResponse, Handle); - HFunc(NHttp::TEvHttpProxy::TEvHttpOutgoingRequest, Handle); - HFunc(NHttp::TEvHttpProxy::TEvAddListeningPort, Handle); - HFunc(NHttp::TEvHttpProxy::TEvRegisterHandler, Handle); - HFunc(NHttp::TEvHttpProxy::TEvHttpIncomingRequest, Handle); - HFunc(NHttp::TEvHttpProxy::TEvHttpOutgoingResponse, Handle); - CFunc(NActors::TEvents::TSystem::Wakeup, HandleRefresh); - } - } -}; - -TCachePolicy GetDefaultCachePolicy(const THttpRequest* request, const TCachePolicy& defaultPolicy) { - TCachePolicy policy = defaultPolicy; - THeaders headers(request->Headers); - TStringBuf cacheControl(headers["Cache-Control"]); - while (TStringBuf cacheItem = cacheControl.NextTok(',')) { - Trim(cacheItem, ' '); - if (cacheItem == "no-store" || cacheItem == "no-cache") { - policy.DiscardCache = true; - } - TStringBuf itemName = cacheItem.NextTok('='); - TrimEnd(itemName, ' '); - TrimBegin(cacheItem, ' '); - if (itemName == "max-age") { - policy.TimeToRefresh = policy.TimeToExpire = TDuration::Seconds(FromString(cacheItem)); - } - if (itemName == "min-fresh") { - policy.TimeToRefresh = policy.TimeToExpire = TDuration::Seconds(FromString(cacheItem)); - } - if (itemName == "stale-if-error") { - policy.KeepOnError = true; - } - } - return policy; -} - -NActors::IActor* CreateHttpCache(const NActors::TActorId& httpProxyId, TGetCachePolicy cachePolicy) { - return new THttpOutgoingCacheActor(httpProxyId, std::move(cachePolicy)); -} - -NActors::IActor* CreateOutgoingHttpCache(const NActors::TActorId& httpProxyId, TGetCachePolicy cachePolicy) { - return new THttpOutgoingCacheActor(httpProxyId, std::move(cachePolicy)); -} - -NActors::IActor* CreateIncomingHttpCache(const NActors::TActorId& httpProxyId, TGetCachePolicy cachePolicy) { - return new THttpIncomingCacheActor(httpProxyId, std::move(cachePolicy)); -} - -} diff --git a/library/cpp/actors/http/http_cache.h b/library/cpp/actors/http/http_cache.h deleted file mode 100644 index ac38bdcac89..00000000000 --- a/library/cpp/actors/http/http_cache.h +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once -#include <library/cpp/actors/core/actor.h> -#include "http.h" - -namespace NHttp { - -struct TCachePolicy { - TDuration TimeToExpire; - TDuration TimeToRefresh; - TDuration PaceToRefresh; - bool KeepOnError = false; - bool DiscardCache = false; - TArrayRef<TString> HeadersToCacheKey; - TArrayRef<TString> StatusesToRetry; - ui32 RetriesCount = 0; - - TCachePolicy() = default; -}; - -using TGetCachePolicy = std::function<TCachePolicy(const THttpRequest*)>; - -NActors::IActor* CreateHttpCache(const NActors::TActorId& httpProxyId, TGetCachePolicy cachePolicy); -NActors::IActor* CreateOutgoingHttpCache(const NActors::TActorId& httpProxyId, TGetCachePolicy cachePolicy); -NActors::IActor* CreateIncomingHttpCache(const NActors::TActorId& httpProxyId, TGetCachePolicy cachePolicy); -TCachePolicy GetDefaultCachePolicy(const THttpRequest* request, const TCachePolicy& policy = TCachePolicy()); - -} diff --git a/library/cpp/actors/http/http_compress.cpp b/library/cpp/actors/http/http_compress.cpp deleted file mode 100644 index b6593fe99d0..00000000000 --- a/library/cpp/actors/http/http_compress.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "http.h" - -#include <zlib.h> - -namespace NHttp { - -TString 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; -} - -TString DecompressDeflate(TStringBuf source) { - z_stream zs = {}; - - if (inflateInit(&zs) != Z_OK) { - throw yexception() << "inflateInit failed while decompressing"; - } - - zs.next_in = (Bytef*)source.data(); - zs.avail_in = source.size(); - - int ret; - char outbuffer[32768]; - TString result; - - // retrieve the decompressed bytes blockwise - do { - zs.next_out = reinterpret_cast<Bytef*>(outbuffer); - zs.avail_out = sizeof(outbuffer); - - ret = inflate(&zs, Z_NO_FLUSH); - - if (result.size() < zs.total_out) { - result.append(outbuffer, zs.total_out - result.size()); - } - } while (ret == Z_OK); - - inflateEnd(&zs); - - if (ret != Z_STREAM_END) { - throw yexception() << "Exception during zlib decompression: (" << ret << ") " << zs.msg; - } - return result; -} - -} diff --git a/library/cpp/actors/http/http_config.h b/library/cpp/actors/http/http_config.h deleted file mode 100644 index 1a2f8646a33..00000000000 --- a/library/cpp/actors/http/http_config.h +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once -#include <util/network/sock.h> -#include <library/cpp/actors/core/log.h> -#include <library/cpp/actors/protos/services_common.pb.h> - -class TInet64StreamSocket; - -namespace NHttp { - -struct THttpConfig { - static constexpr NActors::NLog::EComponent HttpLog = NActorsServices::EServiceCommon::HTTP; - static constexpr size_t BUFFER_SIZE = 64 * 1024; - static constexpr size_t BUFFER_MIN_STEP = 10 * 1024; - static constexpr int LISTEN_QUEUE = 10; - static constexpr TDuration SOCKET_TIMEOUT = TDuration::MilliSeconds(60000); - static constexpr TDuration CONNECTION_TIMEOUT = TDuration::MilliSeconds(60000); - using SocketType = TInet64StreamSocket; - using SocketAddressType = std::shared_ptr<ISockAddr>; -}; - -} diff --git a/library/cpp/actors/http/http_proxy.cpp b/library/cpp/actors/http/http_proxy.cpp deleted file mode 100644 index 74bf4976323..00000000000 --- a/library/cpp/actors/http/http_proxy.cpp +++ /dev/null @@ -1,364 +0,0 @@ -#include <library/cpp/actors/core/events.h> -#include <library/cpp/monlib/metrics/metric_registry.h> -#include "http_proxy.h" - -namespace NHttp { - -class THttpProxy : public NActors::TActorBootstrapped<THttpProxy>, public THttpConfig { -public: - IActor* AddListeningPort(TEvHttpProxy::TEvAddListeningPort::TPtr event, const NActors::TActorContext& ctx) { - IActor* listeningSocket = CreateHttpAcceptorActor(ctx.SelfID, Poller); - TActorId acceptorId = ctx.Register(listeningSocket); - ctx.Send(event->Forward(acceptorId)); - Acceptors.emplace_back(acceptorId); - return listeningSocket; - } - - IActor* AddOutgoingConnection(bool secure, const NActors::TActorContext& ctx) { - IActor* connectionSocket = CreateOutgoingConnectionActor(ctx.SelfID, secure, Poller); - TActorId connectionId = ctx.Register(connectionSocket); - Connections.emplace(connectionId); - return connectionSocket; - } - - void Bootstrap(const NActors::TActorContext& ctx) { - Poller = ctx.Register(NActors::CreatePollerActor()); - Become(&THttpProxy::StateWork); - } - - THttpProxy(std::weak_ptr<NMonitoring::TMetricRegistry> registry) - : Registry(std::move(registry)) - {} - - static constexpr char ActorName[] = "HTTP_PROXY_ACTOR"; - -protected: - STFUNC(StateWork) { - switch (ev->GetTypeRewrite()) { - HFunc(TEvHttpProxy::TEvAddListeningPort, Handle); - HFunc(TEvHttpProxy::TEvRegisterHandler, Handle); - HFunc(TEvHttpProxy::TEvHttpIncomingRequest, Handle); - HFunc(TEvHttpProxy::TEvHttpOutgoingRequest, Handle); - HFunc(TEvHttpProxy::TEvHttpIncomingResponse, Handle); - HFunc(TEvHttpProxy::TEvHttpOutgoingResponse, Handle); - HFunc(TEvHttpProxy::TEvHttpAcceptorClosed, Handle); - HFunc(TEvHttpProxy::TEvHttpConnectionClosed, Handle); - HFunc(TEvHttpProxy::TEvResolveHostRequest, Handle); - HFunc(TEvHttpProxy::TEvReportSensors, Handle); - HFunc(NActors::TEvents::TEvPoison, Handle); - } - } - - void PassAway() override { - Send(Poller, new NActors::TEvents::TEvPoisonPill()); - for (const NActors::TActorId& connection : Connections) { - Send(connection, new NActors::TEvents::TEvPoisonPill()); - } - for (const NActors::TActorId& acceptor : Acceptors) { - Send(acceptor, new NActors::TEvents::TEvPoisonPill()); - } - NActors::TActorBootstrapped<THttpProxy>::PassAway(); - } - - void Handle(TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) { - TStringBuf url = event->Get()->Request->URL.Before('?'); - THashMap<TString, TActorId>::iterator it; - while (!url.empty()) { - it = Handlers.find(url); - if (it != Handlers.end()) { - ctx.Send(event->Forward(it->second)); - return; - } else { - if (url.EndsWith('/')) { - url.Chop(1); - } else { - size_t pos = url.rfind('/'); - if (pos == TStringBuf::npos) { - break; - } else { - url = url.substr(0, pos + 1); - } - } - } - } - ctx.Send(event->Sender, new TEvHttpProxy::TEvHttpOutgoingResponse(event->Get()->Request->CreateResponseNotFound())); - } - - void Handle(TEvHttpProxy::TEvHttpIncomingResponse::TPtr event, const NActors::TActorContext& ctx) { - Y_UNUSED(event); - Y_UNUSED(ctx); - Y_ABORT("This event shouldn't be there, it should go to the http connection owner directly"); - } - - void Handle(TEvHttpProxy::TEvHttpOutgoingResponse::TPtr event, const NActors::TActorContext& ctx) { - Y_UNUSED(event); - Y_UNUSED(ctx); - Y_ABORT("This event shouldn't be there, it should go to the http connection directly"); - } - - void Handle(TEvHttpProxy::TEvHttpOutgoingRequest::TPtr event, const NActors::TActorContext& ctx) { - bool secure(event->Get()->Request->Secure); - NActors::IActor* actor = AddOutgoingConnection(secure, ctx); - ctx.Send(event->Forward(actor->SelfId())); - } - - void Handle(TEvHttpProxy::TEvAddListeningPort::TPtr event, const NActors::TActorContext& ctx) { - AddListeningPort(event, ctx); - } - - void Handle(TEvHttpProxy::TEvHttpAcceptorClosed::TPtr event, const NActors::TActorContext&) { - for (auto it = Acceptors.begin(); it != Acceptors.end(); ++it) { - if (*it == event->Get()->ConnectionID) { - Acceptors.erase(it); - break; - } - } - } - - void Handle(TEvHttpProxy::TEvHttpConnectionClosed::TPtr event, const NActors::TActorContext&) { - Connections.erase(event->Get()->ConnectionID); - } - - void Handle(TEvHttpProxy::TEvRegisterHandler::TPtr event, const NActors::TActorContext& ctx) { - LOG_TRACE_S(ctx, HttpLog, "Register handler " << event->Get()->Path << " to " << event->Get()->Handler); - Handlers[event->Get()->Path] = event->Get()->Handler; - } - - void Handle(TEvHttpProxy::TEvResolveHostRequest::TPtr event, const NActors::TActorContext& ctx) { - const TString& host(event->Get()->Host); - auto it = Hosts.find(host); - if (it == Hosts.end() || it->second.DeadlineTime > ctx.Now()) { - TString addressPart; - TIpPort portPart = 0; - CrackAddress(host, addressPart, portPart); - if (IsIPv6(addressPart)) { - if (it == Hosts.end()) { - it = Hosts.emplace(host, THostEntry()).first; - } - it->second.Address = std::make_shared<TSockAddrInet6>(addressPart.data(), portPart); - it->second.DeadlineTime = ctx.Now() + HostsTimeToLive; - } else if (IsIPv4(addressPart)) { - if (it == Hosts.end()) { - it = Hosts.emplace(host, THostEntry()).first; - } - it->second.Address = std::make_shared<TSockAddrInet>(addressPart.data(), portPart); - it->second.DeadlineTime = ctx.Now() + HostsTimeToLive; - } else { - // TODO(xenoxeno): move to another, possible blocking actor - try { - const NDns::TResolvedHost* result = NDns::CachedResolve(NDns::TResolveInfo(addressPart, portPart)); - if (result != nullptr) { - auto pAddr = result->Addr.Begin(); - while (pAddr != result->Addr.End() && pAddr->ai_family != AF_INET && pAddr->ai_family != AF_INET6) { - ++pAddr; - } - if (pAddr == result->Addr.End()) { - ctx.Send(event->Sender, new TEvHttpProxy::TEvResolveHostResponse("Invalid address family resolved")); - return; - } - THttpConfig::SocketAddressType address; - switch (pAddr->ai_family) { - case AF_INET: - address = std::make_shared<TSockAddrInet>(); - break; - case AF_INET6: - address = std::make_shared<TSockAddrInet6>(); - break; - } - if (address) { - memcpy(address->SockAddr(), pAddr->ai_addr, pAddr->ai_addrlen); - LOG_DEBUG_S(ctx, HttpLog, "Host " << host << " resolved to " << address->ToString()); - if (it == Hosts.end()) { - it = Hosts.emplace(host, THostEntry()).first; - } - it->second.Address = address; - it->second.DeadlineTime = ctx.Now() + HostsTimeToLive; - } - } else { - ctx.Send(event->Sender, new TEvHttpProxy::TEvResolveHostResponse("Error resolving host")); - return; - } - } - catch (const yexception& e) { - ctx.Send(event->Sender, new TEvHttpProxy::TEvResolveHostResponse(e.what())); - return; - } - } - } - ctx.Send(event->Sender, new TEvHttpProxy::TEvResolveHostResponse(it->first, it->second.Address)); - } - - void Handle(TEvHttpProxy::TEvReportSensors::TPtr event, const NActors::TActorContext&) { - const TEvHttpProxy::TEvReportSensors& sensors(*event->Get()); - const static TString urlNotFound = "not-found"; - const TString& url = (sensors.Status == "404" ? urlNotFound : sensors.Url); - - std::shared_ptr<NMonitoring::TMetricRegistry> registry = Registry.lock(); - if (registry) { - registry->Rate( - { - {"sensor", "count"}, - {"direction", sensors.Direction}, - {"peer", sensors.Host}, - {"url", url}, - {"status", sensors.Status} - })->Inc(); - registry->HistogramRate( - { - {"sensor", "time_us"}, - {"direction", sensors.Direction}, - {"peer", sensors.Host}, - {"url", url}, - {"status", sensors.Status} - }, - NMonitoring::ExplicitHistogram({1, 5, 10, 50, 100, 500, 1000, 5000, 10000, 30000, 60000}))->Record(sensors.Time.MicroSeconds()); - registry->HistogramRate( - { - {"sensor", "time_ms"}, - {"direction", sensors.Direction}, - {"peer", sensors.Host}, - {"url", url}, - {"status", sensors.Status} - }, - NMonitoring::ExplicitHistogram({1, 5, 10, 50, 100, 500, 1000, 5000, 10000, 30000, 60000}))->Record(sensors.Time.MilliSeconds()); - } - } - - void Handle(NActors::TEvents::TEvPoison::TPtr, const NActors::TActorContext&) { - for (const TActorId& acceptor : Acceptors) { - Send(acceptor, new NActors::TEvents::TEvPoisonPill()); - } - for (const TActorId& connection : Connections) { - Send(connection, new NActors::TEvents::TEvPoisonPill()); - } - PassAway(); - } - - NActors::TActorId Poller; - TVector<TActorId> Acceptors; - - struct THostEntry { - THttpConfig::SocketAddressType Address; - TInstant DeadlineTime; - }; - - static constexpr TDuration HostsTimeToLive = TDuration::Seconds(60); - - THashMap<TString, THostEntry> Hosts; - THashMap<TString, TActorId> Handlers; - THashSet<TActorId> Connections; // outgoing - std::weak_ptr<NMonitoring::TMetricRegistry> Registry; -}; - -TEvHttpProxy::TEvReportSensors* BuildOutgoingRequestSensors(const THttpOutgoingRequestPtr& request, const THttpIncomingResponsePtr& response) { - return new TEvHttpProxy::TEvReportSensors( - "out", - request->Host, - request->URL.Before('?'), - response ? response->Status : "504", - TDuration::Seconds(std::abs(request->Timer.Passed())) - ); -} - -TEvHttpProxy::TEvReportSensors* BuildIncomingRequestSensors(const THttpIncomingRequestPtr& request, const THttpOutgoingResponsePtr& response) { - const auto& sensors = response->Sensors; - if (sensors) { - return new TEvHttpProxy::TEvReportSensors(*sensors); - } - return new TEvHttpProxy::TEvReportSensors( - "in", - request->Host, - request->URL.Before('?'), - response->Status, - TDuration::Seconds(std::abs(request->Timer.Passed())) - ); -} - -NActors::IActor* CreateHttpProxy(std::weak_ptr<NMonitoring::TMetricRegistry> registry) { - return new THttpProxy(std::move(registry)); -} - -bool IsIPv6(const TString& host) { - if (host.find_first_not_of(":0123456789abcdef") != TString::npos) { - return false; - } - if (std::count(host.begin(), host.end(), ':') < 2) { - return false; - } - return true; -} - -bool IsIPv4(const TString& host) { - if (host.find_first_not_of(".0123456789") != TString::npos) { - return false; - } - if (std::count(host.begin(), host.end(), '.') != 3) { - return false; - } - return true; -} - -bool CrackURL(TStringBuf url, TStringBuf& scheme, TStringBuf& host, TStringBuf& uri) { - url.TrySplit("://", scheme, url); - auto pos = url.find('/'); - if (pos == TStringBuf::npos) { - host = url; - } else { - host = url.substr(0, pos); - uri = url.substr(pos); - } - return true; -} - -void CrackAddress(const TString& address, TString& hostname, TIpPort& port) { - size_t first_colon_pos = address.find(':'); - if (first_colon_pos != TString::npos) { - size_t last_colon_pos = address.rfind(':'); - if (last_colon_pos == first_colon_pos) { - // only one colon, simple case - port = FromStringWithDefault<TIpPort>(address.substr(first_colon_pos + 1), 0); - hostname = address.substr(0, first_colon_pos); - } else { - // ipv6? - size_t closing_bracket_pos = address.rfind(']'); - if (closing_bracket_pos == TString::npos || closing_bracket_pos > last_colon_pos) { - // whole address is ipv6 host - hostname = address; - } else { - port = FromStringWithDefault<TIpPort>(address.substr(last_colon_pos + 1), 0); - hostname = address.substr(0, last_colon_pos); - } - if (hostname.StartsWith('[') && hostname.EndsWith(']')) { - hostname = hostname.substr(1, hostname.size() - 2); - } - } - } else { - hostname = address; - } -} - - -void TrimBegin(TStringBuf& target, char delim) { - while (!target.empty() && *target.begin() == delim) { - target.Skip(1); - } -} - -void TrimEnd(TStringBuf& target, char delim) { - while (!target.empty() && target.back() == delim) { - target.Trunc(target.size() - 1); - } -} - -void Trim(TStringBuf& target, char delim) { - TrimBegin(target, delim); - TrimEnd(target, delim); -} - -void TrimEnd(TString& target, char delim) { - while (!target.empty() && target.back() == delim) { - target.resize(target.size() - 1); - } -} - -} diff --git a/library/cpp/actors/http/http_proxy.h b/library/cpp/actors/http/http_proxy.h deleted file mode 100644 index d9a2c6a71c5..00000000000 --- a/library/cpp/actors/http/http_proxy.h +++ /dev/null @@ -1,246 +0,0 @@ -#pragma once -#include <library/cpp/actors/core/actorsystem.h> -#include <library/cpp/actors/core/actor.h> -#include <library/cpp/actors/core/hfunc.h> -#include <library/cpp/actors/core/events.h> -#include <library/cpp/actors/core/event_local.h> -#include <library/cpp/actors/core/actor_bootstrapped.h> -#include <library/cpp/actors/core/log.h> -#include <library/cpp/actors/interconnect/poller_actor.h> -#include <library/cpp/dns/cache.h> -#include <library/cpp/monlib/metrics/metric_registry.h> -#include <util/generic/variant.h> -#include "http.h" -#include "http_proxy_sock64.h" -#include "http_proxy_ssl.h" - -namespace NHttp { - -struct TSocketDescriptor : NActors::TSharedDescriptor, THttpConfig { - SocketType Socket; - - TSocketDescriptor() = default; - - TSocketDescriptor(int af) - : Socket(af) - { - } - - TSocketDescriptor(SocketType&& s) - : Socket(std::move(s)) - {} - - int GetDescriptor() override { - return static_cast<SOCKET>(Socket); - } -}; - -struct TEvHttpProxy { - enum EEv { - EvAddListeningPort = EventSpaceBegin(NActors::TEvents::ES_HTTP), - EvConfirmListen, - EvRegisterHandler, - EvHttpIncomingRequest, - EvHttpOutgoingRequest, - EvHttpIncomingResponse, - EvHttpOutgoingResponse, - EvHttpConnectionOpened, - EvHttpConnectionClosed, - EvHttpAcceptorClosed, - EvResolveHostRequest, - EvResolveHostResponse, - EvReportSensors, - EvEnd - }; - - static_assert(EvEnd < EventSpaceEnd(NActors::TEvents::ES_HTTP), "ES_HTTP event space is too small."); - - struct TEvAddListeningPort : NActors::TEventLocal<TEvAddListeningPort, EvAddListeningPort> { - TString Address; - TIpPort Port; - TString WorkerName; - bool Secure = false; - TString CertificateFile; - TString PrivateKeyFile; - TString SslCertificatePem; - std::vector<TString> CompressContentTypes; - - TEvAddListeningPort() = default; - - TEvAddListeningPort(TIpPort port) - : Port(port) - {} - - TEvAddListeningPort(TIpPort port, const TString& workerName) - : Port(port) - , WorkerName(workerName) - {} - }; - - struct TEvConfirmListen : NActors::TEventLocal<TEvConfirmListen, EvConfirmListen> { - THttpConfig::SocketAddressType Address; - std::shared_ptr<THttpEndpointInfo> Endpoint; - - TEvConfirmListen(const THttpConfig::SocketAddressType& address, std::shared_ptr<THttpEndpointInfo> endpoint) - : Address(address) - , Endpoint(std::move(endpoint)) - {} - }; - - struct TEvRegisterHandler : NActors::TEventLocal<TEvRegisterHandler, EvRegisterHandler> { - TString Path; - TActorId Handler; - - TEvRegisterHandler(const TString& path, const TActorId& handler) - : Path(path) - , Handler(handler) - {} - }; - - struct TEvHttpIncomingRequest : NActors::TEventLocal<TEvHttpIncomingRequest, EvHttpIncomingRequest> { - THttpIncomingRequestPtr Request; - - TEvHttpIncomingRequest(THttpIncomingRequestPtr request) - : Request(std::move(request)) - {} - }; - - struct TEvHttpOutgoingRequest : NActors::TEventLocal<TEvHttpOutgoingRequest, EvHttpOutgoingRequest> { - THttpOutgoingRequestPtr Request; - TDuration Timeout; - - TEvHttpOutgoingRequest(THttpOutgoingRequestPtr request) - : Request(std::move(request)) - {} - - TEvHttpOutgoingRequest(THttpOutgoingRequestPtr request, TDuration timeout) - : Request(std::move(request)) - , Timeout(timeout) - {} - }; - - struct TEvHttpIncomingResponse : NActors::TEventLocal<TEvHttpIncomingResponse, EvHttpIncomingResponse> { - THttpOutgoingRequestPtr Request; - THttpIncomingResponsePtr Response; - TString Error; - - TEvHttpIncomingResponse(THttpOutgoingRequestPtr request, THttpIncomingResponsePtr response, const TString& error) - : Request(std::move(request)) - , Response(std::move(response)) - , Error(error) - {} - - TEvHttpIncomingResponse(THttpOutgoingRequestPtr request, THttpIncomingResponsePtr response) - : Request(std::move(request)) - , Response(std::move(response)) - {} - - TString GetError() const { - TStringBuilder error; - if (Response != nullptr && !Response->Status.StartsWith('2')) { - error << Response->Status << ' ' << Response->Message; - } - if (!Error.empty()) { - if (!error.empty()) { - error << ';'; - } - error << Error; - } - return error; - } - }; - - struct TEvHttpOutgoingResponse : NActors::TEventLocal<TEvHttpOutgoingResponse, EvHttpOutgoingResponse> { - THttpOutgoingResponsePtr Response; - - TEvHttpOutgoingResponse(THttpOutgoingResponsePtr response) - : Response(std::move(response)) - {} - }; - - struct TEvHttpConnectionOpened : NActors::TEventLocal<TEvHttpConnectionOpened, EvHttpConnectionOpened> { - TString PeerAddress; - TActorId ConnectionID; - - TEvHttpConnectionOpened(const TString& peerAddress, const TActorId& connectionID) - : PeerAddress(peerAddress) - , ConnectionID(connectionID) - {} - }; - - struct TEvHttpConnectionClosed : NActors::TEventLocal<TEvHttpConnectionClosed, EvHttpConnectionClosed> { - TActorId ConnectionID; - TDeque<THttpIncomingRequestPtr> RecycledRequests; - - TEvHttpConnectionClosed(const TActorId& connectionID) - : ConnectionID(connectionID) - {} - - TEvHttpConnectionClosed(const TActorId& connectionID, TDeque<THttpIncomingRequestPtr> recycledRequests) - : ConnectionID(connectionID) - , RecycledRequests(std::move(recycledRequests)) - {} - }; - - struct TEvHttpAcceptorClosed : NActors::TEventLocal<TEvHttpAcceptorClosed, EvHttpAcceptorClosed> { - TActorId ConnectionID; - - TEvHttpAcceptorClosed(const TActorId& connectionID) - : ConnectionID(connectionID) - {} - }; - - struct TEvResolveHostRequest : NActors::TEventLocal<TEvResolveHostRequest, EvResolveHostRequest> { - TString Host; - - TEvResolveHostRequest(const TString& host) - : Host(host) - {} - }; - - struct TEvResolveHostResponse : NActors::TEventLocal<TEvResolveHostResponse, EvResolveHostResponse> { - TString Host; - THttpConfig::SocketAddressType Address; - TString Error; - - TEvResolveHostResponse(const TString& host, THttpConfig::SocketAddressType address) - : Host(host) - , Address(address) - {} - - TEvResolveHostResponse(const TString& error) - : Error(error) - {} - }; - - struct TEvReportSensors : TSensors, NActors::TEventLocal<TEvReportSensors, EvReportSensors> { - using TSensors::TSensors; - - TEvReportSensors(const TSensors& sensors) - : TSensors(sensors) - {} - }; -}; - -struct TPrivateEndpointInfo : THttpEndpointInfo { - TActorId Proxy; - TActorId Owner; - TSslHelpers::TSslHolder<SSL_CTX> SecureContext; - - TPrivateEndpointInfo(const std::vector<TString>& compressContentTypes) - : THttpEndpointInfo(compressContentTypes) - {} -}; - -NActors::IActor* CreateHttpProxy(std::weak_ptr<NMonitoring::TMetricRegistry> registry = NMonitoring::TMetricRegistry::SharedInstance()); -NActors::IActor* CreateHttpAcceptorActor(const TActorId& owner, const TActorId& poller); -NActors::IActor* CreateOutgoingConnectionActor(const TActorId& owner, bool secure, const TActorId& poller); -NActors::IActor* CreateIncomingConnectionActor( - std::shared_ptr<TPrivateEndpointInfo> endpoint, - TIntrusivePtr<TSocketDescriptor> socket, - THttpConfig::SocketAddressType address, - THttpIncomingRequestPtr recycledRequest = nullptr); -TEvHttpProxy::TEvReportSensors* BuildOutgoingRequestSensors(const THttpOutgoingRequestPtr& request, const THttpIncomingResponsePtr& response); -TEvHttpProxy::TEvReportSensors* BuildIncomingRequestSensors(const THttpIncomingRequestPtr& request, const THttpOutgoingResponsePtr& response); - -} diff --git a/library/cpp/actors/http/http_proxy_acceptor.cpp b/library/cpp/actors/http/http_proxy_acceptor.cpp deleted file mode 100644 index c007f747eb3..00000000000 --- a/library/cpp/actors/http/http_proxy_acceptor.cpp +++ /dev/null @@ -1,158 +0,0 @@ -#include <util/network/sock.h> -#include "http_proxy.h" -#include "http_proxy_ssl.h" - -namespace NHttp { - -class TAcceptorActor : public NActors::TActor<TAcceptorActor>, public THttpConfig { -public: - using TBase = NActors::TActor<TAcceptorActor>; - const TActorId Owner; - const TActorId Poller; - TIntrusivePtr<TSocketDescriptor> Socket; - NActors::TPollerToken::TPtr PollerToken; - THashSet<TActorId> Connections; - TDeque<THttpIncomingRequestPtr> RecycledRequests; - std::shared_ptr<TPrivateEndpointInfo> Endpoint; - - TAcceptorActor(const TActorId& owner, const TActorId& poller) - : NActors::TActor<TAcceptorActor>(&TAcceptorActor::StateInit) - , Owner(owner) - , Poller(poller) - { - } - - static constexpr char ActorName[] = "HTTP_ACCEPTOR_ACTOR"; - -protected: - STFUNC(StateListening) { - switch (ev->GetTypeRewrite()) { - HFunc(NActors::TEvPollerRegisterResult, Handle); - HFunc(NActors::TEvPollerReady, Handle); - HFunc(TEvHttpProxy::TEvHttpConnectionClosed, Handle); - HFunc(TEvHttpProxy::TEvReportSensors, Handle); - } - } - - STFUNC(StateInit) { - switch (ev->GetTypeRewrite()) { - HFunc(TEvHttpProxy::TEvAddListeningPort, HandleInit); - } - } - - void HandleInit(TEvHttpProxy::TEvAddListeningPort::TPtr event, const NActors::TActorContext& ctx) { - TString address = event->Get()->Address; - ui16 port = event->Get()->Port; - Socket = new TSocketDescriptor(SocketType::GuessAddressFamily(address)); - // for unit tests :( - SetSockOpt(Socket->Socket, SOL_SOCKET, SO_REUSEADDR, (int)true); -#ifdef SO_REUSEPORT - SetSockOpt(Socket->Socket, SOL_SOCKET, SO_REUSEPORT, (int)true); -#endif - SocketAddressType bindAddress(Socket->Socket.MakeAddress(address, port)); - Endpoint = std::make_shared<TPrivateEndpointInfo>(event->Get()->CompressContentTypes); - Endpoint->Owner = ctx.SelfID; - Endpoint->Proxy = Owner; - Endpoint->WorkerName = event->Get()->WorkerName; - Endpoint->Secure = event->Get()->Secure; - int err = 0; - if (Endpoint->Secure) { - if (!event->Get()->SslCertificatePem.empty()) { - Endpoint->SecureContext = TSslHelpers::CreateServerContext(event->Get()->SslCertificatePem); - } else { - Endpoint->SecureContext = TSslHelpers::CreateServerContext(event->Get()->CertificateFile, event->Get()->PrivateKeyFile); - } - if (Endpoint->SecureContext == nullptr) { - err = -1; - LOG_WARN_S(ctx, HttpLog, "Failed to construct server security context"); - } - } - if (err == 0) { - err = Socket->Socket.Bind(bindAddress.get()); - if (err != 0) { - LOG_WARN_S( - ctx, - HttpLog, - "Failed to bind " << bindAddress->ToString() - << ", code: " << err); - } - } - TStringBuf schema = Endpoint->Secure ? "https://" : "http://"; - if (err == 0) { - err = Socket->Socket.Listen(LISTEN_QUEUE); - if (err == 0) { - LOG_INFO_S(ctx, HttpLog, "Listening on " << schema << bindAddress->ToString()); - SetNonBlock(Socket->Socket); - ctx.Send(Poller, new NActors::TEvPollerRegister(Socket, SelfId(), SelfId())); - TBase::Become(&TAcceptorActor::StateListening); - ctx.Send(event->Sender, new TEvHttpProxy::TEvConfirmListen(bindAddress, Endpoint), 0, event->Cookie); - return; - } else { - LOG_WARN_S( - ctx, - HttpLog, - "Failed to listen on " << schema << bindAddress->ToString() - << ", code: " << err); - } - } - LOG_WARN_S(ctx, HttpLog, "Failed to init - retrying..."); - ctx.ExecutorThread.Schedule(TDuration::Seconds(1), event.Release()); - } - - void Die(const NActors::TActorContext& ctx) override { - ctx.Send(Owner, new TEvHttpProxy::TEvHttpAcceptorClosed(ctx.SelfID)); - for (const NActors::TActorId& connection : Connections) { - ctx.Send(connection, new NActors::TEvents::TEvPoisonPill()); - } - } - - void Handle(NActors::TEvPollerRegisterResult::TPtr ev, const NActors::TActorContext& /*ctx*/) { - PollerToken = std::move(ev->Get()->PollerToken); - PollerToken->Request(true, false); // request read polling - } - - void Handle(NActors::TEvPollerReady::TPtr, const NActors::TActorContext& ctx) { - for (;;) { - SocketAddressType addr; - std::optional<SocketType> s = Socket->Socket.Accept(addr); - if (!s) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { - Y_ABORT_UNLESS(PollerToken); - if (PollerToken->RequestReadNotificationAfterWouldBlock()) { - continue; // we can try it again - } - } - break; - } - TIntrusivePtr<TSocketDescriptor> socket = new TSocketDescriptor(std::move(s).value()); - NActors::IActor* connectionSocket = nullptr; - if (RecycledRequests.empty()) { - connectionSocket = CreateIncomingConnectionActor(Endpoint, socket, addr); - } else { - connectionSocket = CreateIncomingConnectionActor(Endpoint, socket, addr, std::move(RecycledRequests.front())); - RecycledRequests.pop_front(); - } - NActors::TActorId connectionId = ctx.Register(connectionSocket); - ctx.Send(Poller, new NActors::TEvPollerRegister(socket, connectionId, connectionId)); - Connections.emplace(connectionId); - } - } - - void Handle(TEvHttpProxy::TEvHttpConnectionClosed::TPtr event, const NActors::TActorContext&) { - Connections.erase(event->Get()->ConnectionID); - for (auto& req : event->Get()->RecycledRequests) { - req->Clear(); - RecycledRequests.push_back(std::move(req)); - } - } - - void Handle(TEvHttpProxy::TEvReportSensors::TPtr event, const NActors::TActorContext& ctx) { - ctx.Send(event->Forward(Owner)); - } -}; - -NActors::IActor* CreateHttpAcceptorActor(const TActorId& owner, const TActorId& poller) { - return new TAcceptorActor(owner, poller); -} - -} diff --git a/library/cpp/actors/http/http_proxy_incoming.cpp b/library/cpp/actors/http/http_proxy_incoming.cpp deleted file mode 100644 index b98b3c09f36..00000000000 --- a/library/cpp/actors/http/http_proxy_incoming.cpp +++ /dev/null @@ -1,310 +0,0 @@ -#include "http_proxy.h" -#include "http_proxy_sock_impl.h" - -namespace NHttp { - -using namespace NActors; - -template <typename TSocketImpl> -class TIncomingConnectionActor : public TActor<TIncomingConnectionActor<TSocketImpl>>, public TSocketImpl, virtual public THttpConfig { -public: - using TBase = TActor<TIncomingConnectionActor<TSocketImpl>>; - static constexpr bool RecycleRequests = true; - - std::shared_ptr<TPrivateEndpointInfo> Endpoint; - SocketAddressType Address; - TList<THttpIncomingRequestPtr> Requests; - THashMap<THttpIncomingRequestPtr, THttpOutgoingResponsePtr> Responses; - THttpIncomingRequestPtr CurrentRequest; - THttpOutgoingResponsePtr CurrentResponse; - TDeque<THttpIncomingRequestPtr> RecycledRequests; - - THPTimer InactivityTimer; - static constexpr TDuration InactivityTimeout = TDuration::Minutes(2); - TEvPollerReady* InactivityEvent = nullptr; - - TPollerToken::TPtr PollerToken; - - TIncomingConnectionActor( - std::shared_ptr<TPrivateEndpointInfo> endpoint, - TIntrusivePtr<TSocketDescriptor> socket, - SocketAddressType address, - THttpIncomingRequestPtr recycledRequest = nullptr) - : TBase(&TIncomingConnectionActor::StateAccepting) - , TSocketImpl(std::move(socket)) - , Endpoint(std::move(endpoint)) - , Address(address) - { - if (recycledRequest != nullptr) { - RecycledRequests.emplace_back(std::move(recycledRequest)); - } - TSocketImpl::SetNonBlock(); - } - - static constexpr char ActorName[] = "IN_CONNECTION_ACTOR"; - - void CleanupRequest(THttpIncomingRequestPtr& request) { - if (RecycleRequests) { - request->Clear(); - RecycledRequests.push_back(std::move(request)); - } else { - request = nullptr; - } - } - - void CleanupResponse(THttpOutgoingResponsePtr& response) { - CleanupRequest(response->Request); - // TODO: maybe recycle too? - response = nullptr; - } - - TAutoPtr<IEventHandle> AfterRegister(const TActorId& self, const TActorId& parent) override { - return new IEventHandle(self, parent, new TEvents::TEvBootstrap()); - } - - void Die(const TActorContext& ctx) override { - ctx.Send(Endpoint->Owner, new TEvHttpProxy::TEvHttpConnectionClosed(ctx.SelfID, std::move(RecycledRequests))); - TSocketImpl::Shutdown(); - TBase::Die(ctx); - } - -protected: - void Bootstrap(const TActorContext& ctx) { - InactivityTimer.Reset(); - ctx.Schedule(InactivityTimeout, InactivityEvent = new TEvPollerReady(nullptr, false, false)); - LOG_DEBUG_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") incoming connection opened"); - OnAccept(ctx); - } - - void OnAccept(const NActors::TActorContext& ctx) { - int res; - bool read = false, write = false; - for (;;) { - if ((res = TSocketImpl::OnAccept(Endpoint, read, write)) != 1) { - if (-res == EAGAIN) { - if (PollerToken && PollerToken->RequestReadNotificationAfterWouldBlock()) { - continue; - } - return; // wait for further notifications - } else { - LOG_ERROR_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") connection closed - error in Accept: " << strerror(-res)); - return Die(ctx); - } - } - break; - } - TBase::Become(&TIncomingConnectionActor::StateConnected); - ctx.Send(ctx.SelfID, new TEvPollerReady(nullptr, true, true)); - } - - void HandleAccepting(TEvPollerRegisterResult::TPtr ev, const NActors::TActorContext& ctx) { - PollerToken = std::move(ev->Get()->PollerToken); - OnAccept(ctx); - } - - void HandleAccepting(NActors::TEvPollerReady::TPtr, const NActors::TActorContext& ctx) { - OnAccept(ctx); - } - - void HandleConnected(TEvPollerReady::TPtr event, const TActorContext& ctx) { - if (event->Get()->Read) { - for (;;) { - if (CurrentRequest == nullptr) { - if (RecycleRequests && !RecycledRequests.empty()) { - CurrentRequest = std::move(RecycledRequests.front()); - RecycledRequests.pop_front(); - CurrentRequest->Address = Address; - CurrentRequest->Endpoint = Endpoint; - } else { - CurrentRequest = new THttpIncomingRequest(Endpoint, Address); - } - } - if (!CurrentRequest->EnsureEnoughSpaceAvailable()) { - LOG_DEBUG_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") connection closed - not enough space available"); - return Die(ctx); - } - ssize_t need = CurrentRequest->Avail(); - bool read = false, write = false; - ssize_t res = TSocketImpl::Recv(CurrentRequest->Pos(), need, read, write); - if (res > 0) { - InactivityTimer.Reset(); - CurrentRequest->Advance(res); - if (CurrentRequest->IsDone()) { - Requests.emplace_back(CurrentRequest); - CurrentRequest->Timer.Reset(); - if (CurrentRequest->IsReady()) { - LOG_DEBUG_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") -> (" << CurrentRequest->Method << " " << CurrentRequest->URL << ")"); - ctx.Send(Endpoint->Proxy, new TEvHttpProxy::TEvHttpIncomingRequest(CurrentRequest)); - CurrentRequest = nullptr; - } else if (CurrentRequest->IsError()) { - LOG_DEBUG_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") -! (" << CurrentRequest->Method << " " << CurrentRequest->URL << ")"); - bool success = Respond(CurrentRequest->CreateResponseBadRequest(), ctx); - if (!success) { - return; - } - CurrentRequest = nullptr; - } - } - } else if (-res == EAGAIN || -res == EWOULDBLOCK) { - if (PollerToken) { - if (!read && !write) { - read = true; - } - if (PollerToken->RequestNotificationAfterWouldBlock(read, write)) { - continue; - } - } - break; - } else if (-res == EINTR) { - continue; - } else if (!res) { - // connection closed - LOG_DEBUG_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") connection closed"); - return Die(ctx); - } else { - LOG_ERROR_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") connection closed - error in Receive: " << strerror(-res)); - return Die(ctx); - } - } - } - if (event->Get() == InactivityEvent) { - const TDuration passed = TDuration::Seconds(std::abs(InactivityTimer.Passed())); - if (passed >= InactivityTimeout) { - LOG_DEBUG_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") connection closed by inactivity timeout"); - return Die(ctx); // timeout - } else { - ctx.Schedule(InactivityTimeout - passed, InactivityEvent = new TEvPollerReady(nullptr, false, false)); - } - } - if (event->Get()->Write) { - FlushOutput(ctx); - } - } - - void HandleConnected(TEvPollerRegisterResult::TPtr ev, const TActorContext& /*ctx*/) { - PollerToken = std::move(ev->Get()->PollerToken); - PollerToken->Request(true, true); - } - - void HandleConnected(TEvHttpProxy::TEvHttpOutgoingResponse::TPtr event, const TActorContext& ctx) { - Respond(event->Get()->Response, ctx); - } - - bool Respond(THttpOutgoingResponsePtr response, const TActorContext& ctx) { - THttpIncomingRequestPtr request = response->GetRequest(); - response->Finish(); - LOG_DEBUG_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") <- (" << response->Status << " " << response->Message << ")"); - if (!response->Status.StartsWith('2') && response->Status != "404") { - static constexpr size_t MAX_LOGGED_SIZE = 1024; - LOG_DEBUG_S(ctx, HttpLog, - "(#" - << TSocketImpl::GetRawSocket() - << "," - << Address - << ") Request: " - << request->GetObfuscatedData().substr(0, MAX_LOGGED_SIZE)); - LOG_DEBUG_S(ctx, HttpLog, - "(#" - << TSocketImpl::GetRawSocket() - << "," - << Address - << ") Response: " - << TString(response->GetRawData()).substr(0, MAX_LOGGED_SIZE)); - } - THolder<TEvHttpProxy::TEvReportSensors> sensors(BuildIncomingRequestSensors(request, response)); - ctx.Send(Endpoint->Owner, sensors.Release()); - if (request == Requests.front() && CurrentResponse == nullptr) { - CurrentResponse = response; - return FlushOutput(ctx); - } else { - // we are ahead of our pipeline - Responses.emplace(request, response); - return true; - } - } - - bool FlushOutput(const TActorContext& ctx) { - while (CurrentResponse != nullptr) { - size_t size = CurrentResponse->Size(); - if (size == 0) { - Y_ABORT_UNLESS(Requests.front() == CurrentResponse->GetRequest()); - bool close = CurrentResponse->IsConnectionClose(); - Requests.pop_front(); - CleanupResponse(CurrentResponse); - if (!Requests.empty()) { - auto it = Responses.find(Requests.front()); - if (it != Responses.end()) { - CurrentResponse = it->second; - Responses.erase(it); - continue; - } else { - LOG_ERROR_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") connection closed - FlushOutput request not found"); - Die(ctx); - return false; - } - } else { - if (close) { - LOG_DEBUG_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") connection closed"); - Die(ctx); - return false; - } else { - continue; - } - } - } - bool read = false, write = false; - ssize_t res = TSocketImpl::Send(CurrentResponse->Data(), size, read, write); - if (res > 0) { - CurrentResponse->ChopHead(res); - } else if (-res == EINTR) { - continue; - } else if (-res == EAGAIN || -res == EWOULDBLOCK) { - if (PollerToken) { - if (!read && !write) { - write = true; - } - if (PollerToken->RequestNotificationAfterWouldBlock(read, write)) { - continue; - } - } - break; - } else { - CleanupResponse(CurrentResponse); - LOG_ERROR_S(ctx, HttpLog, "(#" << TSocketImpl::GetRawSocket() << "," << Address << ") connection closed - error in FlushOutput: " << strerror(-res)); - Die(ctx); - return false; - } - } - return true; - } - - STFUNC(StateAccepting) { - switch (ev->GetTypeRewrite()) { - CFunc(TEvents::TEvBootstrap::EventType, Bootstrap); - HFunc(TEvPollerReady, HandleAccepting); - HFunc(TEvPollerRegisterResult, HandleAccepting); - } - } - - STFUNC(StateConnected) { - switch (ev->GetTypeRewrite()) { - HFunc(TEvPollerReady, HandleConnected); - HFunc(TEvHttpProxy::TEvHttpOutgoingResponse, HandleConnected); - HFunc(TEvPollerRegisterResult, HandleConnected); - } - } -}; - -IActor* CreateIncomingConnectionActor( - std::shared_ptr<TPrivateEndpointInfo> endpoint, - TIntrusivePtr<TSocketDescriptor> socket, - THttpConfig::SocketAddressType address, - THttpIncomingRequestPtr recycledRequest) { - if (endpoint->Secure) { - return new TIncomingConnectionActor<TSecureSocketImpl>(std::move(endpoint), std::move(socket), address, std::move(recycledRequest)); - } else { - return new TIncomingConnectionActor<TPlainSocketImpl>(std::move(endpoint), std::move(socket), address, std::move(recycledRequest)); - } -} - -} diff --git a/library/cpp/actors/http/http_proxy_outgoing.cpp b/library/cpp/actors/http/http_proxy_outgoing.cpp deleted file mode 100644 index b1f27c2c5a1..00000000000 --- a/library/cpp/actors/http/http_proxy_outgoing.cpp +++ /dev/null @@ -1,335 +0,0 @@ -#include "http_proxy.h" -#include "http_proxy_sock_impl.h" - -namespace NHttp { - -template <typename TSocketImpl> -class TOutgoingConnectionActor : public NActors::TActor<TOutgoingConnectionActor<TSocketImpl>>, public TSocketImpl, virtual public THttpConfig { -public: - using TBase = NActors::TActor<TOutgoingConnectionActor<TSocketImpl>>; - using TSelf = TOutgoingConnectionActor<TSocketImpl>; - const TActorId Owner; - const TActorId Poller; - SocketAddressType Address; - TActorId RequestOwner; - THttpOutgoingRequestPtr Request; - THttpIncomingResponsePtr Response; - TInstant LastActivity; - TDuration ConnectionTimeout = CONNECTION_TIMEOUT; - NActors::TPollerToken::TPtr PollerToken; - - TOutgoingConnectionActor(const TActorId& owner, const TActorId& poller) - : TBase(&TSelf::StateWaiting) - , Owner(owner) - , Poller(poller) - { - } - - static constexpr char ActorName[] = "OUT_CONNECTION_ACTOR"; - - void Die(const NActors::TActorContext& ctx) override { - ctx.Send(Owner, new TEvHttpProxy::TEvHttpConnectionClosed(ctx.SelfID)); - TSocketImpl::Shutdown(); // to avoid errors when connection already closed - TBase::Die(ctx); - } - - TString GetSocketName() { - TStringBuilder builder; - if (TSocketImpl::Socket) { - builder << "(#" << TSocketImpl::GetRawSocket(); - if (Address && Address->SockAddr()->sa_family) { - builder << "," << Address; - } - builder << ") "; - } - return builder; - } - - void ReplyAndDie(const NActors::TActorContext& ctx) { - LOG_DEBUG_S(ctx, HttpLog, GetSocketName() << "-> (" << Response->Status << " " << Response->Message << ")"); - ctx.Send(RequestOwner, new TEvHttpProxy::TEvHttpIncomingResponse(Request, Response)); - RequestOwner = TActorId(); - THolder<TEvHttpProxy::TEvReportSensors> sensors(BuildOutgoingRequestSensors(Request, Response)); - ctx.Send(Owner, sensors.Release()); - LOG_DEBUG_S(ctx, HttpLog, GetSocketName() << "connection closed"); - Die(ctx); - } - - void ReplyErrorAndDie(const NActors::TActorContext& ctx, const TString& error) { - LOG_ERROR_S(ctx, HttpLog, GetSocketName() << "connection closed with error: " << error); - if (RequestOwner) { - ctx.Send(RequestOwner, new TEvHttpProxy::TEvHttpIncomingResponse(Request, Response, error)); - RequestOwner = TActorId(); - THolder<TEvHttpProxy::TEvReportSensors> sensors(BuildOutgoingRequestSensors(Request, Response)); - ctx.Send(Owner, sensors.Release()); - Die(ctx); - } - } - -protected: - void FailConnection(const NActors::TActorContext& ctx, const TString& error) { - if (Request) { - return ReplyErrorAndDie(ctx, error); - } - return TBase::Become(&TOutgoingConnectionActor::StateFailed); - } - - void Connect(const NActors::TActorContext& ctx) { - LOG_DEBUG_S(ctx, HttpLog, GetSocketName() << "connecting"); - TSocketImpl::Create(Address->SockAddr()->sa_family); - TSocketImpl::SetNonBlock(); - TSocketImpl::SetTimeout(ConnectionTimeout); - int res = TSocketImpl::Connect(Address); - RegisterPoller(ctx); - switch (-res) { - case 0: - return OnConnect(ctx); - case EINPROGRESS: - case EAGAIN: - return TBase::Become(&TOutgoingConnectionActor::StateConnecting); - default: - return ReplyErrorAndDie(ctx, strerror(-res)); - } - } - - void FlushOutput(const NActors::TActorContext& ctx) { - if (Request != nullptr) { - Request->Finish(); - while (auto size = Request->Size()) { - bool read = false, write = false; - ssize_t res = TSocketImpl::Send(Request->Data(), size, read, write); - if (res > 0) { - Request->ChopHead(res); - } else if (-res == EINTR) { - continue; - } else if (-res == EAGAIN || -res == EWOULDBLOCK) { - if (PollerToken) { - if (!read && !write) { - write = true; - } - if (PollerToken->RequestNotificationAfterWouldBlock(read, write)) { - continue; - } - } - break; - } else { - if (!res) { - ReplyAndDie(ctx); - } else { - ReplyErrorAndDie(ctx, strerror(-res)); - } - break; - } - } - } - } - - void PullInput(const NActors::TActorContext& ctx) { - for (;;) { - if (Response == nullptr) { - Response = new THttpIncomingResponse(Request); - } - if (!Response->EnsureEnoughSpaceAvailable()) { - return ReplyErrorAndDie(ctx, "Not enough space in socket buffer"); - } - bool read = false, write = false; - ssize_t res = TSocketImpl::Recv(Response->Pos(), Response->Avail(), read, write); - if (res > 0) { - Response->Advance(res); - if (Response->IsDone() && Response->IsReady()) { - return ReplyAndDie(ctx); - } - } else if (-res == EINTR) { - continue; - } else if (-res == EAGAIN || -res == EWOULDBLOCK) { - if (PollerToken) { - if (!read && !write) { - read = true; - } - if (PollerToken->RequestNotificationAfterWouldBlock(read, write)) { - continue; - } - } - return; - } else { - if (!res) { - Response->ConnectionClosed(); - } - if (Response->IsDone() && Response->IsReady()) { - return ReplyAndDie(ctx); - } - return ReplyErrorAndDie(ctx, strerror(-res)); - } - } - } - - void RegisterPoller(const NActors::TActorContext& ctx) { - ctx.Send(Poller, new NActors::TEvPollerRegister(TSocketImpl::Socket, ctx.SelfID, ctx.SelfID)); - } - - void OnConnect(const NActors::TActorContext& ctx) { - bool read = false, write = false; - if (int res = TSocketImpl::OnConnect(read, write); res != 1) { - if (-res == EAGAIN) { - if (PollerToken) { - PollerToken->Request(read, write); - } - return; - } else { - return ReplyErrorAndDie(ctx, strerror(-res)); - } - } - LOG_DEBUG_S(ctx, HttpLog, GetSocketName() << "outgoing connection opened"); - TBase::Become(&TOutgoingConnectionActor::StateConnected); - LOG_DEBUG_S(ctx, HttpLog, GetSocketName() << "<- (" << Request->Method << " " << Request->URL << ")"); - ctx.Send(ctx.SelfID, new NActors::TEvPollerReady(nullptr, true, true)); - } - - static int GetPort(SocketAddressType address) { - switch (address->SockAddr()->sa_family) { - case AF_INET: - return ntohs(reinterpret_cast<sockaddr_in*>(address->SockAddr())->sin_port); - case AF_INET6: - return ntohs(reinterpret_cast<sockaddr_in6*>(address->SockAddr())->sin6_port); - } - return {}; - } - - static void SetPort(SocketAddressType address, int port) { - switch (address->SockAddr()->sa_family) { - case AF_INET: - reinterpret_cast<sockaddr_in*>(address->SockAddr())->sin_port = htons(port); - break; - case AF_INET6: - reinterpret_cast<sockaddr_in6*>(address->SockAddr())->sin6_port = htons(port); - break; - } - } - - void HandleResolving(TEvHttpProxy::TEvResolveHostResponse::TPtr event, const NActors::TActorContext& ctx) { - LastActivity = ctx.Now(); - if (!event->Get()->Error.empty()) { - return FailConnection(ctx, event->Get()->Error); - } - Address = event->Get()->Address; - if (GetPort(Address) == 0) { - SetPort(Address, Request->Secure ? 443 : 80); - } - Connect(ctx); - } - - void HandleConnecting(NActors::TEvPollerReady::TPtr, const NActors::TActorContext& ctx) { - LastActivity = ctx.Now(); - int res = TSocketImpl::GetError(); - if (res == 0) { - OnConnect(ctx); - } else { - FailConnection(ctx, TStringBuilder() << strerror(res)); - } - } - - void HandleConnecting(NActors::TEvPollerRegisterResult::TPtr ev, const NActors::TActorContext& ctx) { - PollerToken = std::move(ev->Get()->PollerToken); - LastActivity = ctx.Now(); - int res = TSocketImpl::GetError(); - if (res == 0) { - OnConnect(ctx); - } else { - FailConnection(ctx, TStringBuilder() << strerror(res)); - } - } - - void HandleWaiting(TEvHttpProxy::TEvHttpOutgoingRequest::TPtr event, const NActors::TActorContext& ctx) { - LastActivity = ctx.Now(); - Request = std::move(event->Get()->Request); - TSocketImpl::SetHost(TString(Request->Host)); - LOG_DEBUG_S(ctx, HttpLog, GetSocketName() << "resolving " << TSocketImpl::Host); - Request->Timer.Reset(); - RequestOwner = event->Sender; - ctx.Send(Owner, new TEvHttpProxy::TEvResolveHostRequest(TSocketImpl::Host)); - if (event->Get()->Timeout) { - ConnectionTimeout = event->Get()->Timeout; - } - ctx.Schedule(ConnectionTimeout, new NActors::TEvents::TEvWakeup()); - LastActivity = ctx.Now(); - TBase::Become(&TOutgoingConnectionActor::StateResolving); - } - - void HandleConnected(NActors::TEvPollerReady::TPtr event, const NActors::TActorContext& ctx) { - LastActivity = ctx.Now(); - if (event->Get()->Write && RequestOwner) { - FlushOutput(ctx); - } - if (event->Get()->Read && RequestOwner) { - PullInput(ctx); - } - } - - void HandleConnected(NActors::TEvPollerRegisterResult::TPtr ev, const NActors::TActorContext& ctx) { - PollerToken = std::move(ev->Get()->PollerToken); - LastActivity = ctx.Now(); - PullInput(ctx); - FlushOutput(ctx); - } - - void HandleFailed(TEvHttpProxy::TEvHttpOutgoingRequest::TPtr event, const NActors::TActorContext& ctx) { - Request = std::move(event->Get()->Request); - RequestOwner = event->Sender; - ReplyErrorAndDie(ctx, "Failed"); - } - - void HandleTimeout(const NActors::TActorContext& ctx) { - TDuration inactivityTime = ctx.Now() - LastActivity; - if (inactivityTime >= ConnectionTimeout) { - FailConnection(ctx, "Connection timed out"); - } else { - ctx.Schedule(Min(ConnectionTimeout - inactivityTime, TDuration::MilliSeconds(100)), new NActors::TEvents::TEvWakeup()); - } - } - - STFUNC(StateWaiting) { - switch (ev->GetTypeRewrite()) { - HFunc(TEvHttpProxy::TEvHttpOutgoingRequest, HandleWaiting); - CFunc(NActors::TEvents::TEvWakeup::EventType, HandleTimeout); - } - } - - STFUNC(StateResolving) { - switch (ev->GetTypeRewrite()) { - HFunc(TEvHttpProxy::TEvResolveHostResponse, HandleResolving); - CFunc(NActors::TEvents::TEvWakeup::EventType, HandleTimeout); - } - } - - STFUNC(StateConnecting) { - switch (ev->GetTypeRewrite()) { - HFunc(NActors::TEvPollerReady, HandleConnecting); - CFunc(NActors::TEvents::TEvWakeup::EventType, HandleTimeout); - HFunc(NActors::TEvPollerRegisterResult, HandleConnecting); - } - } - - STFUNC(StateConnected) { - switch (ev->GetTypeRewrite()) { - HFunc(NActors::TEvPollerReady, HandleConnected); - CFunc(NActors::TEvents::TEvWakeup::EventType, HandleTimeout); - HFunc(NActors::TEvPollerRegisterResult, HandleConnected); - } - } - - STFUNC(StateFailed) { - switch (ev->GetTypeRewrite()) { - HFunc(TEvHttpProxy::TEvHttpOutgoingRequest, HandleFailed); - } - } -}; - -NActors::IActor* CreateOutgoingConnectionActor(const TActorId& owner, bool secure, const TActorId& poller) { - if (secure) { - return new TOutgoingConnectionActor<TSecureSocketImpl>(owner, poller); - } else { - return new TOutgoingConnectionActor<TPlainSocketImpl>(owner, poller); - } -} - -} diff --git a/library/cpp/actors/http/http_proxy_sock64.h b/library/cpp/actors/http/http_proxy_sock64.h deleted file mode 100644 index fa6d9a1e567..00000000000 --- a/library/cpp/actors/http/http_proxy_sock64.h +++ /dev/null @@ -1,147 +0,0 @@ -#pragma once -#include <util/network/sock.h> -#include "http.h" - -class TInet64StreamSocket: public TStreamSocket { -protected: - TInet64StreamSocket(const TInet64StreamSocket& parent, SOCKET fd) - : TStreamSocket(fd) - , AF(parent.AF) - { - } - -public: - TInet64StreamSocket(int af = {}) { - CreateSocket(af); - } - - std::shared_ptr<ISockAddr> MakeAddress(const TString& address, int port) { - if (!address) { - if (AF == AF_INET6) { - return std::make_shared<TSockAddrInet6>("::", port); - } else { - return std::make_shared<TSockAddrInet>(INADDR_ANY, port); - } - } - if (NHttp::IsIPv6(address)) { - return std::make_shared<TSockAddrInet6>(address.data(), port); - } else if (NHttp::IsIPv4(address)) { - return std::make_shared<TSockAddrInet>(address.data(), port); - } - struct addrinfo hints = { - .ai_flags = AI_PASSIVE, - .ai_family = AF, - .ai_socktype = SOCK_STREAM, - }; - struct addrinfo* gai_res = nullptr; - int gai_ret = getaddrinfo(address.data(), nullptr, &hints, &gai_res); - std::shared_ptr<ISockAddr> result; - if (gai_ret == 0 && gai_res->ai_addr) { - switch (gai_res->ai_addr->sa_family) { - case AF_INET6: { - std::shared_ptr<TSockAddrInet6> resultIp6 = std::make_shared<TSockAddrInet6>(); - if (resultIp6->Size() >= gai_res->ai_addrlen) { - memcpy(resultIp6->SockAddr(), gai_res->ai_addr, gai_res->ai_addrlen); - resultIp6->SetPort(port); - result = std::move(resultIp6); - } - } - break; - case AF_INET: { - std::shared_ptr<TSockAddrInet> resultIp4 = std::make_shared<TSockAddrInet>(); - if (resultIp4->Size() >= gai_res->ai_addrlen) { - memcpy(resultIp4->SockAddr(), gai_res->ai_addr, gai_res->ai_addrlen); - resultIp4->SetPort(port); - result = std::move(resultIp4); - } - } - break; - } - } - if (gai_res) { - freeaddrinfo(gai_res); - } - if (result) { - return result; - } - throw yexception() << "Unable to resolve address " << address; - } - - static int GuessAddressFamily(const TString& address) { - if (!address) { - return 0; - } - if (NHttp::IsIPv6(address)) { - return AF_INET6; - } else if (NHttp::IsIPv4(address)) { - return AF_INET; - } - struct addrinfo hints = { - .ai_flags = AI_PASSIVE, - .ai_family = 0, - .ai_socktype = SOCK_STREAM, - }; - int result = 0; - struct addrinfo* gai_res = nullptr; - int gai_ret = getaddrinfo(address.data(), nullptr, &hints, &gai_res); - if (gai_ret == 0 && gai_res->ai_addr) { - switch (gai_res->ai_addr->sa_family) { - case AF_INET: - case AF_INET6: - result = gai_res->ai_addr->sa_family; - break; - } - } - if (gai_res) { - freeaddrinfo(gai_res); - } - return result; - } - - static std::shared_ptr<ISockAddr> MakeAddress(const sockaddr_storage& storage) { - std::shared_ptr<ISockAddr> addr; - switch (storage.ss_family) { - case AF_INET: - addr = std::make_shared<TSockAddrInet>(); - break; - case AF_INET6: - addr = std::make_shared<TSockAddrInet6>(); - break; - } - if (addr) { - memcpy(addr->SockAddr(), &storage, addr->Size()); - } - return addr; - } - - std::optional<TInet64StreamSocket> Accept(std::shared_ptr<ISockAddr>& acceptedAddr) { - sockaddr_storage addrStorage = {}; - socklen_t addrLen = sizeof(addrStorage); - SOCKET s = accept((SOCKET)*this, reinterpret_cast<sockaddr*>(&addrStorage), &addrLen); - if (s == INVALID_SOCKET) { - return {}; - } - acceptedAddr = MakeAddress(addrStorage); - return TInet64StreamSocket(*this, s); - } - -protected: - int AF = AF_UNSPEC; - - void CreateSocket(int af) { - SOCKET s; - if (af == 0) { - s = socket(AF = AF_INET6, SOCK_STREAM, 0); - if (s < 0) { - s = socket(AF = AF_INET, SOCK_STREAM, 0); - } - } else { - s = socket(AF = af, SOCK_STREAM, 0); - } - if (AF == AF_INET6) { - SetSockOpt(s, SOL_SOCKET, IPV6_V6ONLY, (int)false); - } - TSocketHolder sock(s); - sock.Swap(*this); - } -}; diff --git a/library/cpp/actors/http/http_proxy_sock_impl.h b/library/cpp/actors/http/http_proxy_sock_impl.h deleted file mode 100644 index 788c99d9b2c..00000000000 --- a/library/cpp/actors/http/http_proxy_sock_impl.h +++ /dev/null @@ -1,274 +0,0 @@ -#pragma once - -#include "http.h" -#include "http_proxy.h" - -namespace NHttp { - -struct TPlainSocketImpl : virtual public THttpConfig { - TIntrusivePtr<TSocketDescriptor> Socket; - TString Host; - - TPlainSocketImpl() = default; - - void Create(int af) { - Socket = new TSocketDescriptor(af); - } - - TPlainSocketImpl(TIntrusivePtr<TSocketDescriptor> socket) - : Socket(std::move(socket)) - {} - - SOCKET GetRawSocket() const { - return static_cast<SOCKET>(Socket->Socket); - } - - void SetNonBlock(bool nonBlock = true) noexcept { - try { - ::SetNonBlock(Socket->Socket, nonBlock); - } - catch (const yexception&) { - } - } - - void SetTimeout(TDuration timeout) noexcept { - try { - ::SetSocketTimeout(Socket->Socket, timeout.Seconds(), timeout.MilliSecondsOfSecond()); - } - catch (const yexception&) { - } - } - - void Shutdown() { - //Socket->Socket.ShutDown(SHUT_RDWR); // KIKIMR-3895 - if (Socket) { - ::shutdown(Socket->Socket, SHUT_RDWR); - } - } - - int Connect(SocketAddressType address) { - return Socket->Socket.Connect(address.get()); - } - - static constexpr int OnConnect(bool&, bool&) { - return 1; - } - - static int OnAccept(std::shared_ptr<TPrivateEndpointInfo>, bool&, bool&) { - return 1; - } - - bool IsGood() { - int res; - GetSockOpt(Socket->Socket, SOL_SOCKET, SO_ERROR, res); - return res == 0; - } - - int GetError() { - int res; - GetSockOpt(Socket->Socket, SOL_SOCKET, SO_ERROR, res); - return res; - } - - ssize_t Send(const void* data, size_t size, bool&, bool&) { - return Socket->Socket.Send(data, size); - } - - ssize_t Recv(void* data, size_t size, bool&, bool&) { - return Socket->Socket.Recv(data, size); - } - - void SetHost(const TString& host) { - Host = host; - } -}; - -struct TSecureSocketImpl : TPlainSocketImpl, TSslHelpers { - static TSecureSocketImpl* IO(BIO* bio) noexcept { - return static_cast<TSecureSocketImpl*>(BIO_get_data(bio)); - } - - static int IoWrite(BIO* bio, const char* data, int dlen) noexcept { - BIO_clear_retry_flags(bio); - int res = IO(bio)->Socket->Socket.Send(data, dlen); - if (-res == EAGAIN) { - BIO_set_retry_write(bio); - } - return res; - } - - static int IoRead(BIO* bio, char* data, int dlen) noexcept { - BIO_clear_retry_flags(bio); - int res = IO(bio)->Socket->Socket.Recv(data, dlen); - if (-res == EAGAIN) { - BIO_set_retry_read(bio); - } - return res; - } - - static int IoPuts(BIO* bio, const char* buf) noexcept { - Y_UNUSED(bio); - Y_UNUSED(buf); - return -2; - } - - static int IoGets(BIO* bio, char* buf, int size) noexcept { - Y_UNUSED(bio); - Y_UNUSED(buf); - Y_UNUSED(size); - return -2; - } - - static long IoCtrl(BIO* bio, int cmd, long larg, void* parg) noexcept { - Y_UNUSED(larg); - Y_UNUSED(parg); - - if (cmd == BIO_CTRL_FLUSH) { - IO(bio)->Flush(); - return 1; - } - - return -2; - } - - static int IoCreate(BIO* bio) noexcept { - BIO_set_data(bio, nullptr); - BIO_set_init(bio, 1); - return 1; - } - - static int IoDestroy(BIO* bio) noexcept { - BIO_set_data(bio, nullptr); - BIO_set_init(bio, 0); - return 1; - } - - static BIO_METHOD* CreateIoMethod() { - BIO_METHOD* method = BIO_meth_new(BIO_get_new_index() | BIO_TYPE_SOURCE_SINK, "SecureSocketImpl"); - BIO_meth_set_write(method, IoWrite); - BIO_meth_set_read(method, IoRead); - BIO_meth_set_puts(method, IoPuts); - BIO_meth_set_gets(method, IoGets); - BIO_meth_set_ctrl(method, IoCtrl); - BIO_meth_set_create(method, IoCreate); - BIO_meth_set_destroy(method, IoDestroy); - return method; - } - - static BIO_METHOD* IoMethod() { - static BIO_METHOD* method = CreateIoMethod(); - return method; - } - - TSslHolder<BIO> Bio; - TSslHolder<SSL_CTX> Ctx; - TSslHolder<SSL> Ssl; - - TSecureSocketImpl() = default; - - TSecureSocketImpl(TIntrusivePtr<TSocketDescriptor> socket) - : TPlainSocketImpl(std::move(socket)) - {} - - void InitClientSsl() { - Bio.Reset(BIO_new(IoMethod())); - BIO_set_data(Bio.Get(), this); - BIO_set_nbio(Bio.Get(), 1); - Ctx = CreateClientContext(); - Ssl = ConstructSsl(Ctx.Get(), Bio.Get()); - if (!Host.Empty()) { - SSL_set_tlsext_host_name(Ssl.Get(), Host.c_str()); - } - SSL_set_connect_state(Ssl.Get()); - } - - void InitServerSsl(SSL_CTX* ctx) { - Bio.Reset(BIO_new(IoMethod())); - BIO_set_data(Bio.Get(), this); - BIO_set_nbio(Bio.Get(), 1); - Ssl = ConstructSsl(ctx, Bio.Get()); - SSL_set_accept_state(Ssl.Get()); - } - - void Flush() {} - - ssize_t Send(const void* data, size_t size, bool& read, bool& write) { - ssize_t res = SSL_write(Ssl.Get(), data, size); - if (res < 0) { - res = SSL_get_error(Ssl.Get(), res); - switch(res) { - case SSL_ERROR_WANT_READ: - read = true; - return -EAGAIN; - case SSL_ERROR_WANT_WRITE: - write = true; - return -EAGAIN; - default: - return -EIO; - } - } - return res; - } - - ssize_t Recv(void* data, size_t size, bool& read, bool& write) { - ssize_t res = SSL_read(Ssl.Get(), data, size); - if (res < 0) { - res = SSL_get_error(Ssl.Get(), res); - switch(res) { - case SSL_ERROR_WANT_READ: - read = true; - return -EAGAIN; - case SSL_ERROR_WANT_WRITE: - write = true; - return -EAGAIN; - default: - return -EIO; - } - } - return res; - } - - int OnConnect(bool& read, bool& write) { - if (!Ssl) { - InitClientSsl(); - } - int res = SSL_connect(Ssl.Get()); - if (res <= 0) { - res = SSL_get_error(Ssl.Get(), res); - switch(res) { - case SSL_ERROR_WANT_READ: - read = true; - return -EAGAIN; - case SSL_ERROR_WANT_WRITE: - write = true; - return -EAGAIN; - default: - return -EIO; - } - } - return res; - } - - int OnAccept(std::shared_ptr<TPrivateEndpointInfo> endpoint, bool& read, bool& write) { - if (!Ssl) { - InitServerSsl(endpoint->SecureContext.Get()); - } - int res = SSL_accept(Ssl.Get()); - if (res <= 0) { - res = SSL_get_error(Ssl.Get(), res); - switch(res) { - case SSL_ERROR_WANT_READ: - read = true; - return -EAGAIN; - case SSL_ERROR_WANT_WRITE: - write = true; - return -EAGAIN; - default: - return -EIO; - } - } - return res; - } -}; - -} diff --git a/library/cpp/actors/http/http_proxy_ssl.h b/library/cpp/actors/http/http_proxy_ssl.h deleted file mode 100644 index 9953430b1ce..00000000000 --- a/library/cpp/actors/http/http_proxy_ssl.h +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include <openssl/bio.h> -#include <openssl/ssl.h> -#include <openssl/err.h> -#include <openssl/tls1.h> - -namespace NHttp { - -struct TSslHelpers { - struct TSslDestroy { - static void Destroy(SSL_CTX* ctx) noexcept { - SSL_CTX_free(ctx); - } - - static void Destroy(SSL* ssl) noexcept { - SSL_free(ssl); - } - - static void Destroy(X509* cert) noexcept { - X509_free(cert); - } - - static void Destroy(EVP_PKEY* pkey) noexcept { - EVP_PKEY_free(pkey); - } - - static void Destroy(BIO* bio) noexcept { - BIO_free(bio); - } - }; - - template <typename T> - using TSslHolder = THolder<T, TSslDestroy>; - - static TSslHolder<SSL_CTX> CreateSslCtx(const SSL_METHOD* method) { - TSslHolder<SSL_CTX> ctx(SSL_CTX_new(method)); - - if (ctx) { - SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_SSLv2); - SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_SSLv3); - SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_TLSv1); - SSL_CTX_set_options(ctx.Get(), SSL_OP_NO_TLSv1_1); - SSL_CTX_set_options(ctx.Get(), SSL_OP_MICROSOFT_SESS_ID_BUG); - SSL_CTX_set_options(ctx.Get(), SSL_OP_NETSCAPE_CHALLENGE_BUG); - } - - return ctx; - } - - static TSslHolder<SSL_CTX> CreateClientContext() { - return CreateSslCtx(SSLv23_client_method()); - } - - static TSslHolder<SSL_CTX> CreateServerContext(const TString& certificate, const TString& key) { - TSslHolder<SSL_CTX> ctx = CreateSslCtx(SSLv23_server_method()); - SSL_CTX_set_ecdh_auto(ctx.Get(), 1); - int res; - res = SSL_CTX_use_certificate_chain_file(ctx.Get(), certificate.c_str()); - if (res < 0) { - // TODO(xenoxeno): more diagnostics? - return nullptr; - } - res = SSL_CTX_use_PrivateKey_file(ctx.Get(), key.c_str(), SSL_FILETYPE_PEM); - if (res < 0) { - // TODO(xenoxeno): more diagnostics? - return nullptr; - } - return ctx; - } - - static bool LoadX509Chain(TSslHolder<SSL_CTX>& ctx, const TString& pem) { - TSslHolder<BIO> bio(BIO_new_mem_buf(pem.c_str(), pem.size())); - if (bio == nullptr) { - return false; - } - TSslHolder<X509> cert(PEM_read_bio_X509_AUX(bio.Get(), nullptr, nullptr, nullptr)); - if (cert == nullptr) { - return false; - } - if (SSL_CTX_use_certificate(ctx.Get(), cert.Release()) <= 0) { - return false; - } - SSL_CTX_clear_chain_certs(ctx.Get()); - while (true) { - TSslHolder<X509> ca(PEM_read_bio_X509(bio.Get(), nullptr, nullptr, nullptr)); - if (ca == nullptr) { - break; - } - if (!SSL_CTX_add0_chain_cert(ctx.Get(), ca.Release())) { - return false; - } - } - return true; - } - - static bool LoadPrivateKey(TSslHolder<SSL_CTX>& ctx, const TString& pem) { - TSslHolder<BIO> bio(BIO_new_mem_buf(pem.c_str(), pem.size())); - if (bio == nullptr) { - return false; - } - TSslHolder<EVP_PKEY> pkey(PEM_read_bio_PrivateKey(bio.Get(), nullptr, nullptr, nullptr)); - if (SSL_CTX_use_PrivateKey(ctx.Get(), pkey.Release()) <= 0) { - return false; - } - return true; - } - - static TSslHolder<SSL_CTX> CreateServerContext(const TString& pem) { - TSslHolder<SSL_CTX> ctx = CreateSslCtx(SSLv23_server_method()); - SSL_CTX_set_ecdh_auto(ctx.Get(), 1); - if (!LoadX509Chain(ctx, pem)) { - return nullptr; - } - if (!LoadPrivateKey(ctx, pem)) { - return nullptr; - } - return ctx; - } - - static TSslHolder<SSL> ConstructSsl(SSL_CTX* ctx, BIO* bio) { - TSslHolder<SSL> ssl(SSL_new(ctx)); - - if (ssl) { - BIO_up_ref(bio); // SSL_set_bio consumes only one reference if rbio and wbio are the same - SSL_set_bio(ssl.Get(), bio, bio); - } - - return ssl; - } -}; - -} diff --git a/library/cpp/actors/http/http_static.cpp b/library/cpp/actors/http/http_static.cpp deleted file mode 100644 index ff36f5486d6..00000000000 --- a/library/cpp/actors/http/http_static.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "http_proxy.h" -#include "http_static.h" -#include <library/cpp/actors/core/executor_pool_basic.h> -#include <library/cpp/actors/core/log.h> -#include <library/cpp/actors/core/scheduler_basic.h> -#include <library/cpp/actors/http/http.h> -#include <library/cpp/resource/resource.h> -#include <util/folder/path.h> -#include <util/stream/file.h> - -namespace NHttp { - -class THttpStaticContentHandler : public NActors::TActor<THttpStaticContentHandler> { -public: - using TBase = NActors::TActor<THttpStaticContentHandler>; - const TFsPath URL; - const TFsPath FilePath; - const TFsPath ResourcePath; - const TFsPath Index; - - THttpStaticContentHandler(const TString& url, const TString& filePath, const TString& resourcePath, const TString& index) - : TBase(&THttpStaticContentHandler::StateWork) - , URL(url) - , FilePath(filePath) - , ResourcePath(resourcePath) - , Index(index) - {} - - static constexpr char ActorName[] = "HTTP_STATIC_ACTOR"; - - static TInstant GetCompileTime() { - tm compileTime; - strptime(__DATE__ " " __TIME__, "%B %d %Y %H:%M:%S", &compileTime); - return TInstant::Seconds(mktime(&compileTime)); - } - - void Handle(NHttp::TEvHttpProxy::TEvHttpIncomingRequest::TPtr event, const NActors::TActorContext& ctx) { - THttpOutgoingResponsePtr response; - if (event->Get()->Request->Method != "GET") { - response = event->Get()->Request->CreateResponseBadRequest("Wrong request"); - ctx.Send(event->Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(response)); - return; - } - TFsPath url(event->Get()->Request->URL.Before('?')); - if (!url.IsAbsolute()) { - response = event->Get()->Request->CreateResponseBadRequest("Completely wrong URL"); - ctx.Send(event->Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(response)); - return; - } - if (url.GetPath().EndsWith('/') && Index.IsDefined()) { - url /= Index; - } - url = url.RelativeTo(URL); - try { - // TODO: caching? - TString contentType = mimetypeByExt(url.GetExtension().c_str()); - TString data; - TFileStat filestat; - TFsPath resourcename(ResourcePath / url); - if (NResource::FindExact(resourcename.GetPath(), &data)) { - static TInstant compileTime(GetCompileTime()); - filestat.MTime = compileTime.Seconds(); - } else { - TFsPath filename(FilePath / url); - if (!filename.IsSubpathOf(FilePath) && filename != FilePath) { - response = event->Get()->Request->CreateResponseBadRequest("Wrong URL"); - ctx.Send(event->Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(response)); - return; - } - if (filename.Stat(filestat) && filestat.IsFile()) { - data = TUnbufferedFileInput(filename).ReadAll(); - } - } - if (!filestat.IsNull()) { - response = event->Get()->Request->CreateResponseOK(data, contentType, TInstant::Seconds(filestat.MTime)); - } else { - response = event->Get()->Request->CreateResponseNotFound("File not found"); - } - } - catch (const yexception&) { - response = event->Get()->Request->CreateResponseServiceUnavailable("Not available"); - } - ctx.Send(event->Sender, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(response)); - } - - STFUNC(StateWork) { - switch (ev->GetTypeRewrite()) { - HFunc(NHttp::TEvHttpProxy::TEvHttpIncomingRequest, Handle); - } - } -}; - -NActors::IActor* CreateHttpStaticContentHandler(const TString& url, const TString& filePath, const TString& resourcePath, const TString& index) { - return new THttpStaticContentHandler(url, filePath, resourcePath, index); -} - -} diff --git a/library/cpp/actors/http/http_static.h b/library/cpp/actors/http/http_static.h deleted file mode 100644 index f91e15dfb10..00000000000 --- a/library/cpp/actors/http/http_static.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include <library/cpp/actors/core/actor.h> -#include "http.h" - -namespace NHttp { - -NActors::IActor* CreateHttpStaticContentHandler(const TString& url, const TString& filePath, const TString& resourcePath, const TString& index = TString()); - -} diff --git a/library/cpp/actors/http/http_ut.cpp b/library/cpp/actors/http/http_ut.cpp deleted file mode 100644 index e06de078677..00000000000 --- a/library/cpp/actors/http/http_ut.cpp +++ /dev/null @@ -1,509 +0,0 @@ -#include <library/cpp/testing/unittest/registar.h> -#include <library/cpp/testing/unittest/tests_data.h> -#include <library/cpp/actors/core/executor_pool_basic.h> -#include <library/cpp/actors/core/scheduler_basic.h> -#include <library/cpp/actors/testlib/test_runtime.h> -#include <util/system/tempfile.h> -#include "http.h" -#include "http_proxy.h" - - - -enum EService : NActors::NLog::EComponent { - MIN, - Logger, - MVP, - MAX -}; - -namespace { - -template <typename HttpType> -void EatWholeString(TIntrusivePtr<HttpType>& request, const TString& data) { - request->EnsureEnoughSpaceAvailable(data.size()); - auto size = std::min(request->Avail(), data.size()); - memcpy(request->Pos(), data.data(), size); - request->Advance(size); -} - -template <typename HttpType> -void EatPartialString(TIntrusivePtr<HttpType>& request, const TString& data) { - for (char c : data) { - request->EnsureEnoughSpaceAvailable(1); - memcpy(request->Pos(), &c, 1); - request->Advance(1); - } -} - -} - -Y_UNIT_TEST_SUITE(HttpProxy) { - Y_UNIT_TEST(BasicParsing) { - NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); - EatWholeString(request, "GET /test HTTP/1.1\r\nHost: test\r\nSome-Header: 32344\r\n\r\n"); - UNIT_ASSERT_EQUAL(request->Stage, NHttp::THttpIncomingRequest::EParseStage::Done); - UNIT_ASSERT_EQUAL(request->Method, "GET"); - UNIT_ASSERT_EQUAL(request->URL, "/test"); - UNIT_ASSERT_EQUAL(request->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(request->Version, "1.1"); - UNIT_ASSERT_EQUAL(request->Host, "test"); - UNIT_ASSERT_EQUAL(request->Headers, "Host: test\r\nSome-Header: 32344\r\n\r\n"); - } - - Y_UNIT_TEST(GetWithSpecifiedContentType) { - NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); - EatWholeString(request, "GET /test HTTP/1.1\r\nHost: test\r\nContent-Type: application/json\r\nSome-Header: 32344\r\n\r\n"); - UNIT_ASSERT_EQUAL(request->Stage, NHttp::THttpIncomingRequest::EParseStage::Done); - UNIT_ASSERT_EQUAL(request->Method, "GET"); - UNIT_ASSERT_EQUAL(request->URL, "/test"); - UNIT_ASSERT_EQUAL(request->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(request->Version, "1.1"); - UNIT_ASSERT_EQUAL(request->Host, "test"); - UNIT_ASSERT_EQUAL(request->Headers, "Host: test\r\nContent-Type: application/json\r\nSome-Header: 32344\r\n\r\n"); - } - - Y_UNIT_TEST(BasicParsingChunkedBodyRequest) { - NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); - EatWholeString(request, "POST /Url HTTP/1.1\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\n4\r\nthis\r\n4\r\n is \r\n5\r\ntest.\r\n0\r\n\r\n"); - UNIT_ASSERT_EQUAL(request->Stage, NHttp::THttpIncomingRequest::EParseStage::Done); - UNIT_ASSERT_EQUAL(request->Method, "POST"); - UNIT_ASSERT_EQUAL(request->URL, "/Url"); - UNIT_ASSERT_EQUAL(request->Connection, "close"); - UNIT_ASSERT_EQUAL(request->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(request->Version, "1.1"); - UNIT_ASSERT_EQUAL(request->TransferEncoding, "chunked"); - UNIT_ASSERT_EQUAL(request->Body, "this is test."); - } - - Y_UNIT_TEST(BasicPost) { - NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); - EatWholeString(request, "POST /Url HTTP/1.1\r\nConnection: close\r\nContent-Length: 13\r\n\r\nthis is test."); - UNIT_ASSERT_EQUAL(request->Stage, NHttp::THttpIncomingRequest::EParseStage::Done); - UNIT_ASSERT_EQUAL(request->Method, "POST"); - UNIT_ASSERT_EQUAL(request->URL, "/Url"); - UNIT_ASSERT_EQUAL(request->Connection, "close"); - UNIT_ASSERT_EQUAL(request->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(request->Version, "1.1"); - UNIT_ASSERT_EQUAL(request->TransferEncoding, ""); - UNIT_ASSERT_EQUAL(request->Body, "this is test."); - } - - Y_UNIT_TEST(BasicParsingChunkedBodyResponse) { - NHttp::THttpOutgoingRequestPtr request = nullptr; //new NHttp::THttpOutgoingRequest(); - NHttp::THttpIncomingResponsePtr response = new NHttp::THttpIncomingResponse(request); - EatWholeString(response, "HTTP/1.1 200 OK\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\n4\r\nthis\r\n4\r\n is \r\n5\r\ntest.\r\n0\r\n\r\n"); - UNIT_ASSERT_EQUAL(response->Stage, NHttp::THttpIncomingResponse::EParseStage::Done); - UNIT_ASSERT_EQUAL(response->Status, "200"); - UNIT_ASSERT_EQUAL(response->Connection, "close"); - UNIT_ASSERT_EQUAL(response->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(response->Version, "1.1"); - UNIT_ASSERT_EQUAL(response->TransferEncoding, "chunked"); - UNIT_ASSERT_EQUAL(response->Body, "this is test."); - } - - Y_UNIT_TEST(InvalidParsingChunkedBody) { - NHttp::THttpOutgoingRequestPtr request = nullptr; //new NHttp::THttpOutgoingRequest(); - NHttp::THttpIncomingResponsePtr response = new NHttp::THttpIncomingResponse(request); - EatWholeString(response, "HTTP/1.1 200 OK\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nthis\r\n4\r\n is \r\n5\r\ntest.\r\n0\r\n\r\n"); - UNIT_ASSERT(response->IsError()); - } - - Y_UNIT_TEST(AdvancedParsingChunkedBody) { - NHttp::THttpOutgoingRequestPtr request = nullptr; //new NHttp::THttpOutgoingRequest(); - NHttp::THttpIncomingResponsePtr response = new NHttp::THttpIncomingResponse(request); - EatWholeString(response, "HTTP/1.1 200 OK\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\n6\r\nthis\r\n\r\n4\r\n is \r\n5\r\ntest.\r\n0\r\n\r\n"); - UNIT_ASSERT_EQUAL(response->Stage, NHttp::THttpIncomingResponse::EParseStage::Done); - UNIT_ASSERT_EQUAL(response->Status, "200"); - UNIT_ASSERT_EQUAL(response->Connection, "close"); - UNIT_ASSERT_EQUAL(response->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(response->Version, "1.1"); - UNIT_ASSERT_EQUAL(response->TransferEncoding, "chunked"); - UNIT_ASSERT_EQUAL(response->Body, "this\r\n is test."); - } - - 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"); - TString compressedBody = "something very long to compress with deflate algorithm. something very long to compress with deflate algorithm."; - response->EnableCompression(); - size_t size1 = response->Size(); - response->SetBody(compressedBody); - size_t size2 = response->Size(); - size_t compressedBodySize = size2 - size1; - UNIT_ASSERT_VALUES_EQUAL("deflate", response->ContentEncoding); - UNIT_ASSERT(compressedBodySize < compressedBody.size()); - NHttp::THttpOutgoingResponsePtr response2 = response->Duplicate(request); - UNIT_ASSERT_VALUES_EQUAL(response->Body, response2->Body); - UNIT_ASSERT_VALUES_EQUAL(response->ContentLength, response2->ContentLength); - UNIT_ASSERT_VALUES_EQUAL(response->Size(), response2->Size()); - } - - Y_UNIT_TEST(BasicPartialParsing) { - NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); - EatPartialString(request, "GET /test HTTP/1.1\r\nHost: test\r\nSome-Header: 32344\r\n\r\n"); - UNIT_ASSERT_EQUAL(request->Stage, NHttp::THttpIncomingRequest::EParseStage::Done); - UNIT_ASSERT_EQUAL(request->Method, "GET"); - UNIT_ASSERT_EQUAL(request->URL, "/test"); - UNIT_ASSERT_EQUAL(request->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(request->Version, "1.1"); - UNIT_ASSERT_EQUAL(request->Host, "test"); - UNIT_ASSERT_EQUAL(request->Headers, "Host: test\r\nSome-Header: 32344\r\n\r\n"); - } - - Y_UNIT_TEST(BasicPartialParsingChunkedBody) { - NHttp::THttpOutgoingRequestPtr request = nullptr; //new NHttp::THttpOutgoingRequest(); - NHttp::THttpIncomingResponsePtr response = new NHttp::THttpIncomingResponse(request); - EatPartialString(response, "HTTP/1.1 200 OK\r\nConnection: close\r\nTransfer-Encoding: chunked\r\n\r\n4\r\nthis\r\n4\r\n is \r\n5\r\ntest.\r\n0\r\n\r\n"); - UNIT_ASSERT_EQUAL(response->Stage, NHttp::THttpIncomingResponse::EParseStage::Done); - UNIT_ASSERT_EQUAL(response->Status, "200"); - UNIT_ASSERT_EQUAL(response->Connection, "close"); - UNIT_ASSERT_EQUAL(response->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(response->Version, "1.1"); - UNIT_ASSERT_EQUAL(response->TransferEncoding, "chunked"); - UNIT_ASSERT_EQUAL(response->Body, "this is test."); - } - - Y_UNIT_TEST(BasicParsingContentLength0) { - NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); - EatPartialString(request, "GET /test HTTP/1.1\r\nHost: test\r\nContent-Length: 0\r\n\r\n"); - UNIT_ASSERT_EQUAL(request->Stage, NHttp::THttpIncomingRequest::EParseStage::Done); - UNIT_ASSERT_EQUAL(request->Method, "GET"); - UNIT_ASSERT_EQUAL(request->URL, "/test"); - UNIT_ASSERT_EQUAL(request->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(request->Version, "1.1"); - UNIT_ASSERT_EQUAL(request->Host, "test"); - UNIT_ASSERT_EQUAL(request->Headers, "Host: test\r\nContent-Length: 0\r\n\r\n"); - } - - Y_UNIT_TEST(AdvancedParsing) { - NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); - EatWholeString(request, "GE"); - EatWholeString(request, "T"); - EatWholeString(request, " "); - EatWholeString(request, "/test"); - EatWholeString(request, " HTTP/1.1\r"); - EatWholeString(request, "\nHo"); - EatWholeString(request, "st: test"); - EatWholeString(request, "\r\n"); - EatWholeString(request, "Some-Header: 32344\r\n\r"); - EatWholeString(request, "\n"); - UNIT_ASSERT_EQUAL(request->Stage, NHttp::THttpIncomingRequest::EParseStage::Done); - UNIT_ASSERT_EQUAL(request->Method, "GET"); - UNIT_ASSERT_EQUAL(request->URL, "/test"); - UNIT_ASSERT_EQUAL(request->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(request->Version, "1.1"); - UNIT_ASSERT_EQUAL(request->Host, "test"); - UNIT_ASSERT_EQUAL(request->Headers, "Host: test\r\nSome-Header: 32344\r\n\r\n"); - } - - Y_UNIT_TEST(AdvancedPartialParsing) { - NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); - EatPartialString(request, "GE"); - EatPartialString(request, "T"); - EatPartialString(request, " "); - EatPartialString(request, "/test"); - EatPartialString(request, " HTTP/1.1\r"); - EatPartialString(request, "\nHo"); - EatPartialString(request, "st: test"); - EatPartialString(request, "\r\n"); - EatPartialString(request, "Some-Header: 32344\r\n\r"); - EatPartialString(request, "\n"); - UNIT_ASSERT_EQUAL(request->Stage, NHttp::THttpIncomingRequest::EParseStage::Done); - UNIT_ASSERT_EQUAL(request->Method, "GET"); - UNIT_ASSERT_EQUAL(request->URL, "/test"); - UNIT_ASSERT_EQUAL(request->Protocol, "HTTP"); - UNIT_ASSERT_EQUAL(request->Version, "1.1"); - UNIT_ASSERT_EQUAL(request->Host, "test"); - UNIT_ASSERT_EQUAL(request->Headers, "Host: test\r\nSome-Header: 32344\r\n\r\n"); - } - - Y_UNIT_TEST(BasicRenderBodyWithHeadersAndCookies) { - NHttp::THttpOutgoingRequestPtr request = NHttp::THttpOutgoingRequest::CreateRequestGet("http://www.yandex.ru/data/url"); - NHttp::THeadersBuilder headers; - NHttp::TCookiesBuilder cookies; - cookies.Set("cookie1", "123456"); - cookies.Set("cookie2", "45678"); - headers.Set("Cookie", cookies.Render()); - request->Set(headers); - TString requestData = request->AsString(); - UNIT_ASSERT_VALUES_EQUAL(requestData, "GET /data/url HTTP/1.1\r\nHost: www.yandex.ru\r\nAccept: */*\r\nCookie: cookie1=123456; cookie2=45678;\r\n"); - } - - Y_UNIT_TEST(BasicRenderOutgoingResponse) { - NHttp::THttpIncomingRequestPtr request = new NHttp::THttpIncomingRequest(); - EatWholeString(request, "GET /test HTTP/1.1\r\nHost: test\r\nSome-Header: 32344\r\n\r\n"); - - NHttp::THttpOutgoingResponsePtr httpResponseOk = request->CreateResponseOK("response ok"); - UNIT_ASSERT_EQUAL(httpResponseOk->Stage, NHttp::THttpOutgoingResponse::ERenderStage::Done); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseOk->Status, "200"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseOk->Message, "OK"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseOk->ContentType, "text/html"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseOk->Body, "response ok"); - - NHttp::THttpOutgoingResponsePtr httpResponseBadRequest = request->CreateResponseBadRequest(); - UNIT_ASSERT_EQUAL(httpResponseBadRequest->Stage, NHttp::THttpOutgoingResponse::ERenderStage::Done); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseBadRequest->Status, "400"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseBadRequest->Message, "Bad Request"); - UNIT_ASSERT(httpResponseBadRequest->ContentType.empty()); - UNIT_ASSERT(httpResponseBadRequest->Body.empty()); - - NHttp::THttpOutgoingResponsePtr httpResponseNotFound = request->CreateResponseNotFound(); - UNIT_ASSERT_EQUAL(httpResponseNotFound->Stage, NHttp::THttpOutgoingResponse::ERenderStage::Done); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseNotFound->Status, "404"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseNotFound->Message, "Not Found"); - UNIT_ASSERT(httpResponseNotFound->ContentType.empty()); - UNIT_ASSERT(httpResponseNotFound->Body.empty()); - - NHttp::THttpOutgoingResponsePtr httpResponseServiceUnavailable = request->CreateResponseServiceUnavailable(); - UNIT_ASSERT_EQUAL(httpResponseServiceUnavailable->Stage, NHttp::THttpOutgoingResponse::ERenderStage::Done); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseServiceUnavailable->Status, "503"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseServiceUnavailable->Message, "Service Unavailable"); - UNIT_ASSERT(httpResponseServiceUnavailable->ContentType.empty()); - UNIT_ASSERT(httpResponseServiceUnavailable->Body.empty()); - - NHttp::THttpOutgoingResponsePtr httpResponseGatewayTimeout = request->CreateResponseGatewayTimeout("gateway timeout body"); - UNIT_ASSERT_EQUAL(httpResponseGatewayTimeout->Stage, NHttp::THttpOutgoingResponse::ERenderStage::Done); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseGatewayTimeout->Status, "504"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseGatewayTimeout->Message, "Gateway Timeout"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseGatewayTimeout->ContentType, "text/html"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseGatewayTimeout->Body, "gateway timeout body"); - - NHttp::THttpOutgoingResponsePtr httpIncompleteResponse = request->CreateIncompleteResponse("401", "Unauthorized"); - UNIT_ASSERT_EQUAL(httpIncompleteResponse->Stage, NHttp::THttpOutgoingResponse::ERenderStage::Header); - UNIT_ASSERT_STRINGS_EQUAL(httpIncompleteResponse->Status, "401"); - UNIT_ASSERT_STRINGS_EQUAL(httpIncompleteResponse->Message, "Unauthorized"); - - NHttp::THttpOutgoingResponsePtr httpResponse = request->CreateResponse("401", "Unauthorized"); - UNIT_ASSERT_EQUAL(httpResponse->Stage, NHttp::THttpOutgoingResponse::ERenderStage::Done); - UNIT_ASSERT_STRINGS_EQUAL(httpResponse->Status, "401"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponse->Message, "Unauthorized"); - - NHttp::THeadersBuilder headers; - NHttp::TCookiesBuilder cookies; - cookies.Set("cookie1", "123456"); - headers.Set("Set-Cookie", cookies.Render()); - headers.Set("Location", "http://www.yandex.ru/data/url"); - - NHttp::THttpOutgoingResponsePtr httpResponseRedirect = request->CreateResponse("302", "Found", headers); - UNIT_ASSERT_EQUAL(httpResponseRedirect->Stage, NHttp::THttpOutgoingResponse::ERenderStage::Done); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseRedirect->Status, "302"); - UNIT_ASSERT_STRINGS_EQUAL(httpResponseRedirect->Message, "Found"); - UNIT_ASSERT_STRING_CONTAINS(httpResponseRedirect->Headers, "Set-Cookie: cookie1=123456;"); - UNIT_ASSERT_STRING_CONTAINS(httpResponseRedirect->Headers, "Location: http://www.yandex.ru/data/url"); - } - - Y_UNIT_TEST(BasicRunning4) { - NActors::TTestActorRuntimeBase actorSystem; - TPortManager portManager; - TIpPort port = portManager.GetTcpPort(); - TAutoPtr<NActors::IEventHandle> handle; - actorSystem.Initialize(); - //actorSystem.SetLogPriority(NActorsServices::HTTP, NActors::NLog::PRI_DEBUG); - - NActors::IActor* proxy = NHttp::CreateHttpProxy(); - NActors::TActorId proxyId = actorSystem.Register(proxy); - actorSystem.Send(new NActors::IEventHandle(proxyId, TActorId(), new NHttp::TEvHttpProxy::TEvAddListeningPort(port)), 0, true); - actorSystem.DispatchEvents(); - - NActors::TActorId serverId = actorSystem.AllocateEdgeActor(); - actorSystem.Send(new NActors::IEventHandle(proxyId, serverId, new NHttp::TEvHttpProxy::TEvRegisterHandler("/test", serverId)), 0, true); - - NActors::TActorId clientId = actorSystem.AllocateEdgeActor(); - NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestGet("http://127.0.0.1:" + ToString(port) + "/test"); - actorSystem.Send(new NActors::IEventHandle(proxyId, clientId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest(httpRequest)), 0, true); - - NHttp::TEvHttpProxy::TEvHttpIncomingRequest* request = actorSystem.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpIncomingRequest>(handle); - - UNIT_ASSERT_EQUAL(request->Request->URL, "/test"); - - NHttp::THttpOutgoingResponsePtr httpResponse = request->Request->CreateResponseString("HTTP/1.1 200 Found\r\nConnection: Close\r\nTransfer-Encoding: chunked\r\n\r\n6\r\npassed\r\n0\r\n\r\n"); - actorSystem.Send(new NActors::IEventHandle(handle->Sender, serverId, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(httpResponse)), 0, true); - - NHttp::TEvHttpProxy::TEvHttpIncomingResponse* response = actorSystem.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpIncomingResponse>(handle); - - UNIT_ASSERT_EQUAL(response->Response->Status, "200"); - UNIT_ASSERT_EQUAL(response->Response->Body, "passed"); - } - - Y_UNIT_TEST(BasicRunning6) { - NActors::TTestActorRuntimeBase actorSystem; - TPortManager portManager; - TIpPort port = portManager.GetTcpPort(); - TAutoPtr<NActors::IEventHandle> handle; - actorSystem.Initialize(); - //actorSystem.SetLogPriority(NActorsServices::HTTP, NActors::NLog::PRI_DEBUG); - - NActors::IActor* proxy = NHttp::CreateHttpProxy(); - NActors::TActorId proxyId = actorSystem.Register(proxy); - actorSystem.Send(new NActors::IEventHandle(proxyId, TActorId(), new NHttp::TEvHttpProxy::TEvAddListeningPort(port)), 0, true); - actorSystem.DispatchEvents(); - - NActors::TActorId serverId = actorSystem.AllocateEdgeActor(); - actorSystem.Send(new NActors::IEventHandle(proxyId, serverId, new NHttp::TEvHttpProxy::TEvRegisterHandler("/test", serverId)), 0, true); - - NActors::TActorId clientId = actorSystem.AllocateEdgeActor(); - NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestGet("http://[::1]:" + ToString(port) + "/test"); - actorSystem.Send(new NActors::IEventHandle(proxyId, clientId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest(httpRequest)), 0, true); - - NHttp::TEvHttpProxy::TEvHttpIncomingRequest* request = actorSystem.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpIncomingRequest>(handle); - - UNIT_ASSERT_EQUAL(request->Request->URL, "/test"); - - NHttp::THttpOutgoingResponsePtr httpResponse = request->Request->CreateResponseString("HTTP/1.1 200 Found\r\nConnection: Close\r\nTransfer-Encoding: chunked\r\n\r\n6\r\npassed\r\n0\r\n\r\n"); - actorSystem.Send(new NActors::IEventHandle(handle->Sender, serverId, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(httpResponse)), 0, true); - - NHttp::TEvHttpProxy::TEvHttpIncomingResponse* response = actorSystem.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpIncomingResponse>(handle); - - UNIT_ASSERT_EQUAL(response->Response->Status, "200"); - UNIT_ASSERT_EQUAL(response->Response->Body, "passed"); - } - - Y_UNIT_TEST(TlsRunning) { - NActors::TTestActorRuntimeBase actorSystem; - TPortManager portManager; - TIpPort port = portManager.GetTcpPort(); - TAutoPtr<NActors::IEventHandle> handle; - actorSystem.Initialize(); - - TString certificateContent = R"___(-----BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCzRZjodO7Aqe1w -RyOj6kG6g2nn8ZGAxfao4mLT0jDTbVksrhV/h2s3uldLkFo5WrNQ8WZe+iIbXeFL -s8tO6hslzreo9sih2IHoRcH5KnS/6YTqVhRTJb1jE2dM8NwYbwTi+T2Pe0FrBPjI -kgVO50gAtYl9C+fc715uZiSKW+rRlP5OoFTwxrOjiU27RPZjFYyWK9wTI1Es9uRr -lbZbLl5cY6dK2J1AViRraaYKCWO26VbOPWLsY4OD3e+ZXIc3OMCz6Yb0wmRPeJ60 -bbbkGfI8O27kDdv69MAWHIm0yYMzKEnom1dce7rNQNDEqJfocsYIsg+EvayT1yQ9 -KTBegw7LAgMBAAECggEBAKaOCrotqYQmXArsjRhFFDwMy+BKdzyEr93INrlFl0dX -WHpCYobRcbOc1G3H94tB0UdqgAnNqtJyLlb+++ydZAuEOu4oGc8EL+10ofq0jzOd -6Xct8kQt0/6wkFDTlii9PHUDy0X65ZRgUiNGRtg/2I2QG+SpowmI+trm2xwQueFs -VaWrjc3cVvXx0b8Lu7hqZUv08kgC38stzuRk/n2T5VWSAr7Z4ZWQbO918Dv35HUw -Wy/0jNUFP9CBCvFJ4l0OoH9nYhWFG+HXWzNdw6/Hca4jciRKo6esCiOZ9uWYv/ec -/NvX9rgFg8G8/SrTisX10+Bbeq+R1RKwq/IG409TH4ECgYEA14L+3QsgNIUMeYAx -jSCyk22R/tOHI1BM+GtKPUhnwHlAssrcPcxXMJovl6WL93VauYjym0wpCz9urSpA -I2CqTsG8GYciA6Dr3mHgD6cK0jj9UPAU6EnZ5S0mjhPqKZqutu9QegzD2uESvuN8 -36xezwQthzAf0nI/P3sJGjVXjikCgYEA1POm5xcV6SmM6HnIdadEebhzZIJ9TXQz -ry3Jj3a7CKyD5C7fAdkHUTCjgT/2ElxPi9ABkZnC+d/cW9GtJFa0II5qO/agm3KQ -ZXYiutu9A7xACHYFXRiJEjVUdGG9dKMVOHUEa8IHEgrrcUVM/suy/GgutywIfaXs -y58IFP24K9MCgYEAk6zjz7wL+XEiNy+sxLQfKf7vB9sSwxQHakK6wHuY/L8Zomp3 -uLEJHfjJm/SIkK0N2g0JkXkCtv5kbKyC/rsCeK0wo52BpVLjzaLr0k34kE0U6B1b -dkEE2pGx1bG3x4KDLj+Wuct9ecK5Aa0IqIyI+vo16GkFpUM8K9e3SQo8UOECgYEA -sCZYAkILYtJ293p9giz5rIISGasDAUXE1vxWBXEeJ3+kneTTnZCrx9Im/ewtnWR0 -fF90XL9HFDDD88POqAd8eo2zfKR2l/89SGBfPBg2EtfuU9FkgGyiPciVcqvC7q9U -B15saMKX3KnhtdGwbfeLt9RqCCTJZT4SUSDcq5hwdvcCgYAxY4Be8mNipj8Cgg22 -mVWSolA0TEzbtUcNk6iGodpi+Z0LKpsPC0YRqPRyh1K+rIltG1BVdmUBHcMlOYxl -lWWvbJH6PkJWy4n2MF7PO45kjN3pPZg4hgH63JjZeAineBwEArUGb9zHnvzcdRvF -wuQ2pZHL/HJ0laUSieHDJ5917w== ------END PRIVATE KEY----- - - ------BEGIN CERTIFICATE----- -MIIDjTCCAnWgAwIBAgIURt5IBx0J3xgEaQvmyrFH2A+NkpMwDQYJKoZIhvcNAQEL -BQAwVjELMAkGA1UEBhMCUlUxDzANBgNVBAgMBk1vc2NvdzEPMA0GA1UEBwwGTW9z -Y293MQ8wDQYDVQQKDAZZYW5kZXgxFDASBgNVBAMMC3Rlc3Qtc2VydmVyMB4XDTE5 -MDkyMDE3MTQ0MVoXDTQ3MDIwNDE3MTQ0MVowVjELMAkGA1UEBhMCUlUxDzANBgNV -BAgMBk1vc2NvdzEPMA0GA1UEBwwGTW9zY293MQ8wDQYDVQQKDAZZYW5kZXgxFDAS -BgNVBAMMC3Rlc3Qtc2VydmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEAs0WY6HTuwKntcEcjo+pBuoNp5/GRgMX2qOJi09Iw021ZLK4Vf4drN7pXS5Ba -OVqzUPFmXvoiG13hS7PLTuobJc63qPbIodiB6EXB+Sp0v+mE6lYUUyW9YxNnTPDc -GG8E4vk9j3tBawT4yJIFTudIALWJfQvn3O9ebmYkilvq0ZT+TqBU8Mazo4lNu0T2 -YxWMlivcEyNRLPbka5W2Wy5eXGOnStidQFYka2mmCgljtulWzj1i7GODg93vmVyH -NzjAs+mG9MJkT3ietG225BnyPDtu5A3b+vTAFhyJtMmDMyhJ6JtXXHu6zUDQxKiX -6HLGCLIPhL2sk9ckPSkwXoMOywIDAQABo1MwUTAdBgNVHQ4EFgQUDv/xuJ4CvCgG -fPrZP3hRAt2+/LwwHwYDVR0jBBgwFoAUDv/xuJ4CvCgGfPrZP3hRAt2+/LwwDwYD -VR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAinKpMYaA2tjLpAnPVbjy -/ZxSBhhB26RiQp3Re8XOKyhTWqgYE6kldYT0aXgK9x9mPC5obQannDDYxDc7lX+/ -qP/u1X81ZcDRo/f+qQ3iHfT6Ftt/4O3qLnt45MFM6Q7WabRm82x3KjZTqpF3QUdy -tumWiuAP5DMd1IRDtnKjFHO721OsEsf6NLcqdX89bGeqXDvrkwg3/PNwTyW5E7cj -feY8L2eWtg6AJUnIBu11wvfzkLiH3QKzHvO/SIZTGf5ihDsJ3aKEE9UNauTL3bVc -CRA/5XcX13GJwHHj6LCoc3sL7mt8qV9HKY2AOZ88mpObzISZxgPpdKCfjsrdm63V -6g== ------END CERTIFICATE-----)___"; - - TTempFileHandle certificateFile; - - certificateFile.Write(certificateContent.data(), certificateContent.size()); - - NActors::IActor* proxy = NHttp::CreateHttpProxy(); - NActors::TActorId proxyId = actorSystem.Register(proxy); - - THolder<NHttp::TEvHttpProxy::TEvAddListeningPort> add = MakeHolder<NHttp::TEvHttpProxy::TEvAddListeningPort>(port); - ///////// https configuration - add->Secure = true; - add->CertificateFile = certificateFile.Name(); - add->PrivateKeyFile = certificateFile.Name(); - ///////// - actorSystem.Send(new NActors::IEventHandle(proxyId, TActorId(), add.Release()), 0, true); - actorSystem.DispatchEvents(); - - NActors::TActorId serverId = actorSystem.AllocateEdgeActor(); - actorSystem.Send(new NActors::IEventHandle(proxyId, serverId, new NHttp::TEvHttpProxy::TEvRegisterHandler("/test", serverId)), 0, true); - - NActors::TActorId clientId = actorSystem.AllocateEdgeActor(); - NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestGet("https://[::1]:" + ToString(port) + "/test"); - actorSystem.Send(new NActors::IEventHandle(proxyId, clientId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest(httpRequest)), 0, true); - - NHttp::TEvHttpProxy::TEvHttpIncomingRequest* request = actorSystem.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpIncomingRequest>(handle); - - UNIT_ASSERT_EQUAL(request->Request->URL, "/test"); - - NHttp::THttpOutgoingResponsePtr httpResponse = request->Request->CreateResponseString("HTTP/1.1 200 Found\r\nConnection: Close\r\nTransfer-Encoding: chunked\r\n\r\n6\r\npassed\r\n0\r\n\r\n"); - actorSystem.Send(new NActors::IEventHandle(handle->Sender, serverId, new NHttp::TEvHttpProxy::TEvHttpOutgoingResponse(httpResponse)), 0, true); - - NHttp::TEvHttpProxy::TEvHttpIncomingResponse* response = actorSystem.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpIncomingResponse>(handle); - - UNIT_ASSERT_EQUAL(response->Response->Status, "200"); - UNIT_ASSERT_EQUAL(response->Response->Body, "passed"); - } - - /*Y_UNIT_TEST(AdvancedRunning) { - THolder<NActors::TActorSystemSetup> setup = MakeHolder<NActors::TActorSystemSetup>(); - setup->NodeId = 1; - setup->ExecutorsCount = 1; - setup->Executors = new TAutoPtr<NActors::IExecutorPool>[1]; - setup->Executors[0] = new NActors::TBasicExecutorPool(0, 2, 10); - setup->Scheduler = new NActors::TBasicSchedulerThread(NActors::TSchedulerConfig(512, 100)); - NActors::TActorSystem actorSystem(setup); - actorSystem.Start(); - NHttp::THttpProxy* incomingProxy = new NHttp::THttpProxy(); - NActors::TActorId incomingProxyId = actorSystem.Register(incomingProxy); - actorSystem.Send(incomingProxyId, new NHttp::TEvHttpProxy::TEvAddListeningPort(13337)); - - NHttp::THttpProxy* outgoingProxy = new NHttp::THttpProxy(); - NActors::TActorId outgoingProxyId = actorSystem.Register(outgoingProxy); - - THolder<NHttp::THttpStaticStringRequest> httpRequest = MakeHolder<NHttp::THttpStaticStringRequest>("GET /test HTTP/1.1\r\n\r\n"); - actorSystem.Send(outgoingProxyId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest("[::]:13337", std::move(httpRequest))); - - Sleep(TDuration::Minutes(60)); - }*/ - - Y_UNIT_TEST(TooLongHeader) { - NActors::TTestActorRuntimeBase actorSystem; - actorSystem.SetUseRealInterconnect(); - TPortManager portManager; - TIpPort port = portManager.GetTcpPort(); - TAutoPtr<NActors::IEventHandle> handle; - actorSystem.Initialize(); - - NActors::IActor* proxy = NHttp::CreateHttpProxy(); - NActors::TActorId proxyId = actorSystem.Register(proxy); - actorSystem.Send(new NActors::IEventHandle(proxyId, TActorId(), new NHttp::TEvHttpProxy::TEvAddListeningPort(port)), 0, true); - actorSystem.DispatchEvents(); - - NActors::TActorId serverId = actorSystem.AllocateEdgeActor(); - actorSystem.Send(new NActors::IEventHandle(proxyId, serverId, new NHttp::TEvHttpProxy::TEvRegisterHandler("/test", serverId)), 0, true); - - NActors::TActorId clientId = actorSystem.AllocateEdgeActor(); - NHttp::THttpOutgoingRequestPtr httpRequest = NHttp::THttpOutgoingRequest::CreateRequestGet("http://[::1]:" + ToString(port) + "/test"); - httpRequest->Set("Connection", "close"); - TString longHeader; - longHeader.append(9000, 'X'); - httpRequest->Set(longHeader, "data"); - actorSystem.Send(new NActors::IEventHandle(proxyId, clientId, new NHttp::TEvHttpProxy::TEvHttpOutgoingRequest(httpRequest)), 0, true); - - NHttp::TEvHttpProxy::TEvHttpIncomingResponse* response = actorSystem.GrabEdgeEvent<NHttp::TEvHttpProxy::TEvHttpIncomingResponse>(handle); - - UNIT_ASSERT_EQUAL(response->Response->Status, "400"); - UNIT_ASSERT_EQUAL(response->Response->Body, "Invalid http header"); - } -} diff --git a/library/cpp/actors/http/ut/CMakeLists.darwin-arm64.txt b/library/cpp/actors/http/ut/CMakeLists.darwin-arm64.txt deleted file mode 100644 index f9c9afac615..00000000000 --- a/library/cpp/actors/http/ut/CMakeLists.darwin-arm64.txt +++ /dev/null @@ -1,67 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - - -add_executable(library-cpp-actors-http-ut) -target_include_directories(library-cpp-actors-http-ut PRIVATE - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http -) -target_link_libraries(library-cpp-actors-http-ut PUBLIC - contrib-libs-cxxsupp - yutil - cpp-testing-unittest_main - cpp-actors-http - cpp-actors-testlib -) -target_link_options(library-cpp-actors-http-ut PRIVATE - -Wl,-platform_version,macos,11.0,11.0 - -fPIC - -fPIC - -framework - CoreFoundation -) -target_sources(library-cpp-actors-http-ut PRIVATE - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_ut.cpp -) -set_property( - TARGET - library-cpp-actors-http-ut - PROPERTY - SPLIT_FACTOR - 1 -) -add_yunittest( - NAME - library-cpp-actors-http-ut - TEST_TARGET - library-cpp-actors-http-ut - TEST_ARG - --print-before-suite - --print-before-test - --fork-tests - --print-times - --show-fails -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - LABELS - SMALL -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - PROCESSORS - 1 -) -target_allocator(library-cpp-actors-http-ut - system_allocator -) -vcs_info(library-cpp-actors-http-ut) diff --git a/library/cpp/actors/http/ut/CMakeLists.darwin-x86_64.txt b/library/cpp/actors/http/ut/CMakeLists.darwin-x86_64.txt deleted file mode 100644 index 99677acae5e..00000000000 --- a/library/cpp/actors/http/ut/CMakeLists.darwin-x86_64.txt +++ /dev/null @@ -1,68 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - - -add_executable(library-cpp-actors-http-ut) -target_include_directories(library-cpp-actors-http-ut PRIVATE - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http -) -target_link_libraries(library-cpp-actors-http-ut PUBLIC - contrib-libs-cxxsupp - yutil - library-cpp-cpuid_check - cpp-testing-unittest_main - cpp-actors-http - cpp-actors-testlib -) -target_link_options(library-cpp-actors-http-ut PRIVATE - -Wl,-platform_version,macos,11.0,11.0 - -fPIC - -fPIC - -framework - CoreFoundation -) -target_sources(library-cpp-actors-http-ut PRIVATE - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_ut.cpp -) -set_property( - TARGET - library-cpp-actors-http-ut - PROPERTY - SPLIT_FACTOR - 1 -) -add_yunittest( - NAME - library-cpp-actors-http-ut - TEST_TARGET - library-cpp-actors-http-ut - TEST_ARG - --print-before-suite - --print-before-test - --fork-tests - --print-times - --show-fails -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - LABELS - SMALL -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - PROCESSORS - 1 -) -target_allocator(library-cpp-actors-http-ut - system_allocator -) -vcs_info(library-cpp-actors-http-ut) diff --git a/library/cpp/actors/http/ut/CMakeLists.linux-aarch64.txt b/library/cpp/actors/http/ut/CMakeLists.linux-aarch64.txt deleted file mode 100644 index 8818e4418fe..00000000000 --- a/library/cpp/actors/http/ut/CMakeLists.linux-aarch64.txt +++ /dev/null @@ -1,71 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - - -add_executable(library-cpp-actors-http-ut) -target_include_directories(library-cpp-actors-http-ut PRIVATE - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http -) -target_link_libraries(library-cpp-actors-http-ut PUBLIC - contrib-libs-linux-headers - contrib-libs-cxxsupp - yutil - cpp-testing-unittest_main - cpp-actors-http - cpp-actors-testlib -) -target_link_options(library-cpp-actors-http-ut PRIVATE - -ldl - -lrt - -Wl,--no-as-needed - -fPIC - -fPIC - -lpthread - -lrt - -ldl -) -target_sources(library-cpp-actors-http-ut PRIVATE - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_ut.cpp -) -set_property( - TARGET - library-cpp-actors-http-ut - PROPERTY - SPLIT_FACTOR - 1 -) -add_yunittest( - NAME - library-cpp-actors-http-ut - TEST_TARGET - library-cpp-actors-http-ut - TEST_ARG - --print-before-suite - --print-before-test - --fork-tests - --print-times - --show-fails -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - LABELS - SMALL -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - PROCESSORS - 1 -) -target_allocator(library-cpp-actors-http-ut - cpp-malloc-jemalloc -) -vcs_info(library-cpp-actors-http-ut) diff --git a/library/cpp/actors/http/ut/CMakeLists.linux-x86_64.txt b/library/cpp/actors/http/ut/CMakeLists.linux-x86_64.txt deleted file mode 100644 index 620f66ad003..00000000000 --- a/library/cpp/actors/http/ut/CMakeLists.linux-x86_64.txt +++ /dev/null @@ -1,73 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - - -add_executable(library-cpp-actors-http-ut) -target_include_directories(library-cpp-actors-http-ut PRIVATE - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http -) -target_link_libraries(library-cpp-actors-http-ut PUBLIC - contrib-libs-linux-headers - contrib-libs-cxxsupp - yutil - library-cpp-cpuid_check - cpp-testing-unittest_main - cpp-actors-http - cpp-actors-testlib -) -target_link_options(library-cpp-actors-http-ut PRIVATE - -ldl - -lrt - -Wl,--no-as-needed - -fPIC - -fPIC - -lpthread - -lrt - -ldl -) -target_sources(library-cpp-actors-http-ut PRIVATE - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http/http_ut.cpp -) -set_property( - TARGET - library-cpp-actors-http-ut - PROPERTY - SPLIT_FACTOR - 1 -) -add_yunittest( - NAME - library-cpp-actors-http-ut - TEST_TARGET - library-cpp-actors-http-ut - TEST_ARG - --print-before-suite - --print-before-test - --fork-tests - --print-times - --show-fails -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - LABELS - SMALL -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - PROCESSORS - 1 -) -target_allocator(library-cpp-actors-http-ut - cpp-malloc-tcmalloc - libs-tcmalloc-no_percpu_cache -) -vcs_info(library-cpp-actors-http-ut) diff --git a/library/cpp/actors/http/ut/CMakeLists.txt b/library/cpp/actors/http/ut/CMakeLists.txt deleted file mode 100644 index 2dce3a77fe3..00000000000 --- a/library/cpp/actors/http/ut/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - -if (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64" AND NOT HAVE_CUDA) - include(CMakeLists.linux-aarch64.txt) -elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64") - include(CMakeLists.darwin-x86_64.txt) -elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64") - include(CMakeLists.darwin-arm64.txt) -elseif (WIN32 AND CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64" AND NOT HAVE_CUDA) - include(CMakeLists.windows-x86_64.txt) -elseif (CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND NOT HAVE_CUDA) - include(CMakeLists.linux-x86_64.txt) -endif() diff --git a/library/cpp/actors/http/ut/CMakeLists.windows-x86_64.txt b/library/cpp/actors/http/ut/CMakeLists.windows-x86_64.txt deleted file mode 100644 index 73603d626cd..00000000000 --- a/library/cpp/actors/http/ut/CMakeLists.windows-x86_64.txt +++ /dev/null @@ -1,58 +0,0 @@ - -# This file was generated by the build system used internally in the Yandex monorepo. -# Only simple modifications are allowed (adding source-files to targets, adding simple properties -# like target_include_directories). These modifications will be ported to original -# ya.make files by maintainers. Any complex modifications which can't be ported back to the -# original buildsystem will not be accepted. - - - -add_executable(library-cpp-actors-http-ut) -target_include_directories(library-cpp-actors-http-ut PRIVATE - ${CMAKE_SOURCE_DIR}/library/cpp/actors/http -) -target_link_libraries(library-cpp-actors-http-ut PUBLIC - contrib-libs-cxxsupp - yutil - library-cpp-cpuid_check - cpp-testing-unittest_main - cpp-actors-http - cpp-actors-testlib -) -set_property( - TARGET - library-cpp-actors-http-ut - PROPERTY - SPLIT_FACTOR - 1 -) -add_yunittest( - NAME - library-cpp-actors-http-ut - TEST_TARGET - library-cpp-actors-http-ut - TEST_ARG - --print-before-suite - --print-before-test - --fork-tests - --print-times - --show-fails -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - LABELS - SMALL -) -set_yunittest_property( - TEST - library-cpp-actors-http-ut - PROPERTY - PROCESSORS - 1 -) -target_allocator(library-cpp-actors-http-ut - system_allocator -) -vcs_info(library-cpp-actors-http-ut) diff --git a/library/cpp/actors/http/ut/ya.make b/library/cpp/actors/http/ut/ya.make deleted file mode 100644 index 84043080534..00000000000 --- a/library/cpp/actors/http/ut/ya.make +++ /dev/null @@ -1,16 +0,0 @@ -UNITTEST_FOR(library/cpp/actors/http) - -SIZE(SMALL) - -PEERDIR( - library/cpp/actors/testlib -) - -IF (NOT OS_WINDOWS) -SRCS( - http_ut.cpp -) -ELSE() -ENDIF() - -END() diff --git a/library/cpp/actors/http/ya.make b/library/cpp/actors/http/ya.make deleted file mode 100644 index 9b66988ea9a..00000000000 --- a/library/cpp/actors/http/ya.make +++ /dev/null @@ -1,36 +0,0 @@ -LIBRARY() - -SRCS( - http_cache.cpp - http_cache.h - http_compress.cpp - http_config.h - http_proxy_acceptor.cpp - http_proxy_incoming.cpp - http_proxy_outgoing.cpp - http_proxy_sock_impl.h - http_proxy_sock64.h - http_proxy_ssl.h - http_proxy.cpp - http_proxy.h - http_static.cpp - http_static.h - http.cpp - http.h -) - -PEERDIR( - contrib/libs/openssl - contrib/libs/zlib - library/cpp/actors/core - library/cpp/actors/interconnect - library/cpp/dns - library/cpp/monlib/metrics - library/cpp/string_utils/quote -) - -END() - -RECURSE_FOR_TESTS( - ut -) |
