diff options
author | Daniil Cherednik <dan.cherednik@gmail.com> | 2022-11-24 13:14:34 +0300 |
---|---|---|
committer | Daniil Cherednik <dan.cherednik@gmail.com> | 2022-11-24 14:46:00 +0300 |
commit | 87f7fceed34bcafb8aaff351dd493a35c916986f (patch) | |
tree | 26809ec8f550aba8eb019e59adc3d48e51913eb2 /library/cpp/actors/http | |
parent | 11bc4015b8010ae201bf3eb33db7dba425aca35e (diff) | |
download | ydb-38c0b87ea9b8ab54a793f4246ecdee802a8227dc.tar.gz |
Ydb stable 22-4-4322.4.43
x-stable-origin-commit: 8d49d46cc834835bf3e50870516acd7376a63bcf
Diffstat (limited to 'library/cpp/actors/http')
-rw-r--r-- | library/cpp/actors/http/http.cpp | 28 | ||||
-rw-r--r-- | library/cpp/actors/http/http_proxy_acceptor.cpp | 16 | ||||
-rw-r--r-- | library/cpp/actors/http/http_proxy_sock64.h | 29 |
3 files changed, 58 insertions, 15 deletions
diff --git a/library/cpp/actors/http/http.cpp b/library/cpp/actors/http/http.cpp index 7da6ace0b9..5d0c25fa8c 100644 --- a/library/cpp/actors/http/http.cpp +++ b/library/cpp/actors/http/http.cpp @@ -22,6 +22,10 @@ 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"; } @@ -126,13 +130,16 @@ void THttpParser<THttpRequest, TSocketBuffer>::Advance(size_t len) { [[fallthrough]]; } case EParseStage::Body: { - if (!ContentLength.empty()) { - if (ProcessData(Content, data, FromString(ContentLength))) { + 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 (TEqNoCase()(TransferEncoding, "chunked")) { - Stage = EParseStage::ChunkLength; } else if (TotalSize.has_value()) { if (ProcessData(Content, data, GetBodySizeFromTotalSize())) { Body = Content; @@ -282,16 +289,19 @@ void THttpParser<THttpResponse, TSocketBuffer>::Advance(size_t len) { [[fallthrough]]; } case EParseStage::Body: { - if (!ContentLength.empty()) { - if (ProcessData(Body, data, FromString(ContentLength))) { + 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 (TEqNoCase()(TransferEncoding, "chunked")) { - Stage = EParseStage::ChunkLength; } else if (TotalSize.has_value()) { if (ProcessData(Content, data, GetBodySizeFromTotalSize())) { Body = Content; @@ -401,9 +411,11 @@ THttpOutgoingResponsePtr THttpIncomingRequest::CreateResponseString(TStringBuf d } } } + 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"); diff --git a/library/cpp/actors/http/http_proxy_acceptor.cpp b/library/cpp/actors/http/http_proxy_acceptor.cpp index c44921fe0c..3c90f8cbe9 100644 --- a/library/cpp/actors/http/http_proxy_acceptor.cpp +++ b/library/cpp/actors/http/http_proxy_acceptor.cpp @@ -19,13 +19,7 @@ public: : NActors::TActor<TAcceptorActor>(&TAcceptorActor::StateInit) , Owner(owner) , Poller(poller) - , Socket(new TSocketDescriptor()) { - // 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 } protected: @@ -45,7 +39,15 @@ protected: } void HandleInit(TEvHttpProxy::TEvAddListeningPort::TPtr event, const NActors::TActorContext& ctx) { - SocketAddressType bindAddress(Socket->Socket.MakeAddress(event->Get()->Address,event->Get()->Port)); + 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; diff --git a/library/cpp/actors/http/http_proxy_sock64.h b/library/cpp/actors/http/http_proxy_sock64.h index 29b7b34b47..9b7db8f662 100644 --- a/library/cpp/actors/http/http_proxy_sock64.h +++ b/library/cpp/actors/http/http_proxy_sock64.h @@ -67,6 +67,35 @@ public: 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, + }; + 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: + return gai_res->ai_addr->sa_family; + } + } + if (gai_res) { + freeaddrinfo(gai_res); + } + return 0; + } + static std::shared_ptr<ISockAddr> MakeAddress(const sockaddr_storage& storage) { std::shared_ptr<ISockAddr> addr; switch (storage.ss_family) { |