aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/actors/http
diff options
context:
space:
mode:
authorDaniil Cherednik <dan.cherednik@gmail.com>2022-11-24 13:14:34 +0300
committerDaniil Cherednik <dan.cherednik@gmail.com>2022-11-24 14:46:00 +0300
commit87f7fceed34bcafb8aaff351dd493a35c916986f (patch)
tree26809ec8f550aba8eb019e59adc3d48e51913eb2 /library/cpp/actors/http
parent11bc4015b8010ae201bf3eb33db7dba425aca35e (diff)
downloadydb-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.cpp28
-rw-r--r--library/cpp/actors/http/http_proxy_acceptor.cpp16
-rw-r--r--library/cpp/actors/http/http_proxy_sock64.h29
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) {