summaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/http
diff options
context:
space:
mode:
authorrobot-piglet <[email protected]>2023-12-04 15:32:14 +0300
committerrobot-piglet <[email protected]>2023-12-05 01:22:50 +0300
commitc21ed9eedf73010bc81342518177dfdfb0d56bd7 (patch)
tree72f8fde4463080cfe5a38eb0babc051cfe32c51e /library/cpp/actors/http
parentec1311bf2e8cc231723b8b5e484ca576663a1309 (diff)
Intermediate changes
Diffstat (limited to 'library/cpp/actors/http')
-rw-r--r--library/cpp/actors/http/CMakeLists.darwin-arm64.txt32
-rw-r--r--library/cpp/actors/http/CMakeLists.darwin-x86_64.txt32
-rw-r--r--library/cpp/actors/http/CMakeLists.linux-aarch64.txt33
-rw-r--r--library/cpp/actors/http/CMakeLists.linux-x86_64.txt33
-rw-r--r--library/cpp/actors/http/CMakeLists.txt19
-rw-r--r--library/cpp/actors/http/CMakeLists.windows-x86_64.txt32
-rw-r--r--library/cpp/actors/http/http.cpp823
-rw-r--r--library/cpp/actors/http/http.h877
-rw-r--r--library/cpp/actors/http/http_cache.cpp608
-rw-r--r--library/cpp/actors/http/http_cache.h27
-rw-r--r--library/cpp/actors/http/http_compress.cpp76
-rw-r--r--library/cpp/actors/http/http_config.h21
-rw-r--r--library/cpp/actors/http/http_proxy.cpp364
-rw-r--r--library/cpp/actors/http/http_proxy.h246
-rw-r--r--library/cpp/actors/http/http_proxy_acceptor.cpp158
-rw-r--r--library/cpp/actors/http/http_proxy_incoming.cpp310
-rw-r--r--library/cpp/actors/http/http_proxy_outgoing.cpp335
-rw-r--r--library/cpp/actors/http/http_proxy_sock64.h147
-rw-r--r--library/cpp/actors/http/http_proxy_sock_impl.h274
-rw-r--r--library/cpp/actors/http/http_proxy_ssl.h133
-rw-r--r--library/cpp/actors/http/http_static.cpp97
-rw-r--r--library/cpp/actors/http/http_static.h9
-rw-r--r--library/cpp/actors/http/http_ut.cpp509
-rw-r--r--library/cpp/actors/http/ut/CMakeLists.darwin-arm64.txt67
-rw-r--r--library/cpp/actors/http/ut/CMakeLists.darwin-x86_64.txt68
-rw-r--r--library/cpp/actors/http/ut/CMakeLists.linux-aarch64.txt71
-rw-r--r--library/cpp/actors/http/ut/CMakeLists.linux-x86_64.txt73
-rw-r--r--library/cpp/actors/http/ut/CMakeLists.txt19
-rw-r--r--library/cpp/actors/http/ut/CMakeLists.windows-x86_64.txt58
-rw-r--r--library/cpp/actors/http/ut/ya.make16
-rw-r--r--library/cpp/actors/http/ya.make36
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
-)