diff options
author | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-17 12:04:09 +0300 |
---|---|---|
committer | arcadia-devtools <arcadia-devtools@yandex-team.ru> | 2022-02-17 12:04:09 +0300 |
commit | 2c8e314f8fff8633fe2cf026badfbf6180845ae0 (patch) | |
tree | c3b650d13934ec1315e3660d60fd2275f09b03a7 /library/cpp/http/misc | |
parent | a49ae9d891c35087b242c854f69880fd9fecbddd (diff) | |
download | ydb-2c8e314f8fff8633fe2cf026badfbf6180845ae0.tar.gz |
intermediate changes
ref:d5f945ecdc1f5af1ad57e12787c6b8ed1a9f0f12
Diffstat (limited to 'library/cpp/http/misc')
-rw-r--r-- | library/cpp/http/misc/httpreqdata.cpp | 211 | ||||
-rw-r--r-- | library/cpp/http/misc/httpreqdata.h | 81 | ||||
-rw-r--r-- | library/cpp/http/misc/httpreqdata_ut.cpp | 42 | ||||
-rw-r--r-- | library/cpp/http/misc/ya.make | 1 |
4 files changed, 155 insertions, 180 deletions
diff --git a/library/cpp/http/misc/httpreqdata.cpp b/library/cpp/http/misc/httpreqdata.cpp index f6951f68cd..f02611bc58 100644 --- a/library/cpp/http/misc/httpreqdata.cpp +++ b/library/cpp/http/misc/httpreqdata.cpp @@ -1,145 +1,123 @@ #include "httpreqdata.h" +#include <library/cpp/case_insensitive_string/case_insensitive_string.h> #include <util/stream/mem.h> TBaseServerRequestData::TBaseServerRequestData(SOCKET s) - : Addr(nullptr) - , Host() - , Port() - , Path(nullptr) - , Search(nullptr) - , SearchLength(0) - , Socket(s) - , BeginTime(MicroSeconds()) + : Socket_(s) + , BeginTime_(MicroSeconds()) { } -TBaseServerRequestData::TBaseServerRequestData(const char* qs, SOCKET s) - : Addr(nullptr) - , Host() - , Port() - , Path(nullptr) - , Search((char*)qs) - , SearchLength(qs ? strlen(qs) : 0) - , OrigSearch(Search, SearchLength) - , Socket(s) - , BeginTime(MicroSeconds()) +TBaseServerRequestData::TBaseServerRequestData(TStringBuf qs, SOCKET s) + : Query_(qs) + , OrigQuery_(Query_) + , Socket_(s) + , BeginTime_(MicroSeconds()) { } -void TBaseServerRequestData::AppendQueryString(const char* str, size_t length) { - if (Y_UNLIKELY(Search)) { - Y_ASSERT(strlen(Search) == SearchLength); - ModifiedQueryString.Reserve(SearchLength + length + 2); - ModifiedQueryString.Assign(Search, SearchLength); - if (SearchLength > 0 && Search[SearchLength - 1] != '&' && - length > 0 && str[0] != '&') { - ModifiedQueryString.Append('&'); - } - ModifiedQueryString.Append(str, length); - } else { - ModifiedQueryString.Reserve(length + 1); - ModifiedQueryString.Assign(str, length); - } - ModifiedQueryString.Append('\0'); - Search = ModifiedQueryString.data(); - SearchLength = ModifiedQueryString.size() - 1; // ignore terminator +void TBaseServerRequestData::AppendQueryString(TStringBuf str) { + if (Y_UNLIKELY(!Query_.empty())) { + TStringBuf separator = !Query_.EndsWith('&') && !str.StartsWith('&') ? "&"sv : ""sv; + ModifiedQueryString_ = TString::Join(Query_, separator, str); + } else { + ModifiedQueryString_ = str; + } + Query_ = ModifiedQueryString_; } void TBaseServerRequestData::SetRemoteAddr(TStringBuf addr) { - TMemoryOutput out(AddrData, Y_ARRAY_SIZE(AddrData) - 1); - out.Write(addr.substr(0, Y_ARRAY_SIZE(AddrData) - 1)); - *out.Buf() = '\0'; - - Addr = AddrData; + Addr_.ConstructInPlace(addr.substr(0, INET6_ADDRSTRLEN - 1)); } -const char* TBaseServerRequestData::RemoteAddr() const { - if (!Addr) { - *AddrData = 0; - GetRemoteAddr(Socket, AddrData, sizeof(AddrData)); - Addr = AddrData; - } - - return Addr; -} +TStringBuf TBaseServerRequestData::RemoteAddr() const { + if (!Addr_) { + auto& addr = Addr_.ConstructInPlace(); + addr.ReserveAndResize(INET6_ADDRSTRLEN); + if (GetRemoteAddr(Socket_, addr.begin(), sizeof(INET6_ADDRSTRLEN))) { + if (auto pos = addr.find('\0'); pos != TString::npos) { + addr.resize(pos); + } + } else { + addr.clear(); + } + } -const char* TBaseServerRequestData::HeaderIn(TStringBuf key) const { - auto it = HeadersIn_.find(key); + return *Addr_; + } - if (it == HeadersIn_.end()) { - return nullptr; - } +const TString* TBaseServerRequestData::HeaderIn(TStringBuf key) const { + return HeadersIn_.FindPtr(key); +} - return it->second.data(); +TStringBuf TBaseServerRequestData::HeaderInOrEmpty(TStringBuf key) const { + const auto* ptr = HeaderIn(key); + return ptr ? TStringBuf{*ptr} : TStringBuf{}; } TString TBaseServerRequestData::HeaderByIndex(size_t n) const noexcept { - if (n >= HeadersCount()) { - return nullptr; + if (n >= HeadersIn_.size()) { + return {}; } - THttpHeadersContainer::const_iterator i = HeadersIn_.begin(); - - while (n) { - ++i; - --n; - } + const auto& [key, value] = *std::next(HeadersIn_.begin(), n); - return TString(i->first) + TStringBuf(": ") + i->second; + return TString::Join(key, ": ", value); } -const char* TBaseServerRequestData::Environment(const char* key) const { - if (stricmp(key, "REMOTE_ADDR") == 0) { - const char* ip = HeaderIn("X-Real-IP"); - if (ip) - return ip; - return RemoteAddr(); - } else if (stricmp(key, "QUERY_STRING") == 0) { - return QueryString(); - } else if (stricmp(key, "SERVER_NAME") == 0) { - return ServerName().data(); - } else if (stricmp(key, "SERVER_PORT") == 0) { - return ServerPort().data(); - } else if (stricmp(key, "SCRIPT_NAME") == 0) { +TStringBuf TBaseServerRequestData::Environment(TStringBuf key) const { + TCaseInsensitiveStringBuf ciKey(key.data(), key.size()); + if (ciKey == "REMOTE_ADDR") { + const auto ip = HeaderIn("X-Real-IP"); + return ip ? *ip : RemoteAddr(); + } else if (ciKey == "QUERY_STRING") { + return Query(); + } else if (ciKey == "SERVER_NAME") { + return ServerName(); + } else if (ciKey == "SERVER_PORT") { + return ServerPort(); + } else if (ciKey == "SCRIPT_NAME") { return ScriptName(); } - return nullptr; + return {}; } -void TBaseServerRequestData::Clear() { + void TBaseServerRequestData::Clear() { HeadersIn_.clear(); - Addr = Path = Search = nullptr; - OrigSearch = {}; - SearchLength = 0; - Host.clear(); - Port.clear(); - CurPage.remove(); - ParseBuf.Clear(); - BeginTime = MicroSeconds(); + Addr_ = Nothing(); + Path_.clear(); + Query_ = {}; + OrigQuery_ = {}; + Host_.clear(); + Port_.clear(); + CurPage_.remove(); + ParseBuf_.clear(); + BeginTime_ = MicroSeconds(); } -const char* TBaseServerRequestData::GetCurPage() const { - if (!CurPage && Host) { - CurPage = "http://"; - CurPage += Host; - if (Port) { - CurPage += ':'; - CurPage += Port; +const TString& TBaseServerRequestData::GetCurPage() const { + if (!CurPage_ && Host_) { + CurPage_ = "http://"; + CurPage_ += Host_; + if (Port_) { + CurPage_ += ':'; + CurPage_ += Port_; } - CurPage += Path; - if (Search) { - CurPage += '?'; - CurPage += Search; + CurPage_ += Path_; + if (Query_) { + CurPage_ += '?'; + CurPage_ += Query_; } } - return CurPage.data(); + return CurPage_; } -bool TBaseServerRequestData::Parse(const char* origReq) { - size_t origReqLength = strlen(origReq); - ParseBuf.Assign(origReq, origReqLength + 1); - char* req = ParseBuf.Data(); +bool TBaseServerRequestData::Parse(TStringBuf origReqBuf) { + ParseBuf_.reserve(origReqBuf.size() + 1); + ParseBuf_.assign(origReqBuf.begin(), origReqBuf.end()); + ParseBuf_.push_back('\0'); + char* req = ParseBuf_.data(); while (*req == ' ' || *req == '\t') req++; @@ -161,20 +139,20 @@ bool TBaseServerRequestData::Parse(const char* origReq) { *fragment = 0; // ignore fragment else fragment = urlEnd; - Path = req; + char* path = req; // calculate Search length without additional strlen-ing - Search = strchr(Path, '?'); - if (Search) { - *Search++ = 0; - ptrdiff_t delta = fragment - Search; + char* query = strchr(path, '?'); + if (query) { + *query++ = 0; + ptrdiff_t delta = fragment - query; // indeed, second case is a parse error - SearchLength = (delta >= 0) ? delta : (urlEnd - Search); - Y_ASSERT(strlen(Search) == SearchLength); + Query_ = {query, static_cast<size_t>(delta >= 0 ? delta : (urlEnd - query))}; } else { - SearchLength = 0; + Query_ = {}; } - OrigSearch = {Search, SearchLength}; + Path_ = path; + OrigQuery_ = Query_; return true; } @@ -185,12 +163,11 @@ void TBaseServerRequestData::AddHeader(const TString& name, const TString& value if (stricmp(name.data(), "Host") == 0) { size_t hostLen = strcspn(value.data(), ":"); if (value[hostLen] == ':') - Port = value.substr(hostLen + 1); - Host = value.substr(0, hostLen); + Port_ = value.substr(hostLen + 1); + Host_ = value.substr(0, hostLen); } } -void TBaseServerRequestData::SetPath(const TString& path) { - PathStorage = TBuffer(path.data(), path.size() + 1); - Path = PathStorage.Data(); +void TBaseServerRequestData::SetPath(TString path) { + Path_ = std::move(path); } diff --git a/library/cpp/http/misc/httpreqdata.h b/library/cpp/http/misc/httpreqdata.h index 16e59c4d78..b5c9e446a9 100644 --- a/library/cpp/http/misc/httpreqdata.h +++ b/library/cpp/http/misc/httpreqdata.h @@ -13,52 +13,52 @@ #include <util/system/yassert.h> #include <util/generic/string.h> #include <util/datetime/base.h> -#include <util/generic/buffer.h> +#include <util/generic/vector.h> +#include <util/generic/maybe.h> using THttpHeadersContainer = THashMap<TString, TString, TCIOps, TCIOps>; class TBaseServerRequestData { public: TBaseServerRequestData(SOCKET s = INVALID_SOCKET); - TBaseServerRequestData(const char* qs, SOCKET s = INVALID_SOCKET); + TBaseServerRequestData(TStringBuf qs, SOCKET s = INVALID_SOCKET); void SetHost(const TString& host, ui16 port) { - Host = host; - Port = ToString(port); + Host_ = host; + Port_ = ToString(port); } const TString& ServerName() const { - return Host; + return Host_; } NAddr::IRemoteAddrPtr ServerAddress() const { - return NAddr::GetSockAddr(Socket); + return NAddr::GetSockAddr(Socket_); } const TString& ServerPort() const { - return Port; + return Port_; } - const char* ScriptName() const { - return Path; + TStringBuf ScriptName() const { + return Path_; } - const char* QueryString() const { - return Search; + TStringBuf Query() const { + return Query_; } - TStringBuf QueryStringBuf() const { - return TStringBuf(Search, SearchLength); + TStringBuf OrigQuery() const { + return OrigQuery_; } - TStringBuf OrigQueryStringBuf() const { - return OrigSearch; - } - - void AppendQueryString(const char* str, size_t length); - const char* RemoteAddr() const; + void AppendQueryString(TStringBuf str); + TStringBuf RemoteAddr() const; void SetRemoteAddr(TStringBuf addr); - const char* HeaderIn(TStringBuf key) const; + // Returns nullptr when the header does not exist + const TString* HeaderIn(TStringBuf key) const; + // Throws on missing header + TStringBuf HeaderInOrEmpty(TStringBuf key) const; const THttpHeadersContainer& HeadersIn() const { return HeadersIn_; @@ -69,39 +69,36 @@ public: } TString HeaderByIndex(size_t n) const noexcept; - const char* Environment(const char* key) const; + TStringBuf Environment(TStringBuf key) const; void Clear(); void SetSocket(SOCKET s) noexcept { - Socket = s; + Socket_ = s; } ui64 RequestBeginTime() const noexcept { - return BeginTime; + return BeginTime_; } - void SetPath(const TString& path); - const char* GetCurPage() const; - bool Parse(const char* req); + void SetPath(TString path); + const TString& GetCurPage() const; + bool Parse(TStringBuf req); void AddHeader(const TString& name, const TString& value); private: - TBuffer PathStorage; - mutable char* Addr; - TString Host; - TString Port; - char* Path; - char* Search; - size_t SearchLength; // length of Search - TStringBuf OrigSearch; + mutable TMaybe<TString> Addr_; + TString Host_; + TString Port_; + TString Path_; + TStringBuf Query_; + TStringBuf OrigQuery_; THttpHeadersContainer HeadersIn_; - mutable char AddrData[INET6_ADDRSTRLEN]; - SOCKET Socket; - ui64 BeginTime; - mutable TString CurPage; - TBuffer ParseBuf; - TBuffer ModifiedQueryString; + SOCKET Socket_; + ui64 BeginTime_; + mutable TString CurPage_; + TVector<char> ParseBuf_; + TString ModifiedQueryString_; }; class TServerRequestData: public TBaseServerRequestData { @@ -110,14 +107,14 @@ public: : TBaseServerRequestData(s) { } - TServerRequestData(const char* qs, SOCKET s = INVALID_SOCKET) + TServerRequestData(TStringBuf qs, SOCKET s = INVALID_SOCKET) : TBaseServerRequestData(qs, s) { Scan(); } void Scan() { - CgiParam.Scan(QueryStringBuf()); + CgiParam.Scan(Query()); } public: diff --git a/library/cpp/http/misc/httpreqdata_ut.cpp b/library/cpp/http/misc/httpreqdata_ut.cpp index e7f16ef27c..3e13046fd0 100644 --- a/library/cpp/http/misc/httpreqdata_ut.cpp +++ b/library/cpp/http/misc/httpreqdata_ut.cpp @@ -13,8 +13,8 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) { sd.AddHeader("x-XxX", "y-yyy"); UNIT_ASSERT_VALUES_EQUAL(sd.HeadersCount(), 2); - UNIT_ASSERT_VALUES_EQUAL(TStringBuf(sd.HeaderIn("X-XX")), TStringBuf("y-yy")); - UNIT_ASSERT_VALUES_EQUAL(TStringBuf(sd.HeaderIn("X-XXX")), TStringBuf("y-yyy")); + UNIT_ASSERT_VALUES_EQUAL(sd.HeaderInOrEmpty("X-XX"), TStringBuf("y-yy")); + UNIT_ASSERT_VALUES_EQUAL(sd.HeaderInOrEmpty("X-XXX"), TStringBuf("y-yyy")); } Y_UNIT_TEST(ComplexHeaders) { @@ -23,21 +23,21 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) { sd.AddHeader("x-Xx", "y-yy"); UNIT_ASSERT_VALUES_EQUAL(sd.HeadersCount(), 1); - UNIT_ASSERT_VALUES_EQUAL(TStringBuf(sd.HeaderIn("X-XX")), TStringBuf("y-yy")); + UNIT_ASSERT_VALUES_EQUAL(sd.HeaderInOrEmpty("X-XX"), TStringBuf("y-yy")); sd.AddHeader("x-Xz", "y-yy"); UNIT_ASSERT_VALUES_EQUAL(sd.HeadersCount(), 2); - UNIT_ASSERT_VALUES_EQUAL(TStringBuf(sd.HeaderIn("X-Xz")), TStringBuf("y-yy")); + UNIT_ASSERT_VALUES_EQUAL(sd.HeaderInOrEmpty("X-Xz"), TStringBuf("y-yy")); UNIT_ASSERT_VALUES_EQUAL(sd.ServerName(), "zzz"); UNIT_ASSERT_VALUES_EQUAL(sd.ServerPort(), "1"); sd.AddHeader("Host", "1234"); UNIT_ASSERT_VALUES_EQUAL(sd.HeadersCount(), 3); - UNIT_ASSERT_VALUES_EQUAL(TStringBuf(sd.HeaderIn("Host")), TStringBuf("1234")); + UNIT_ASSERT_VALUES_EQUAL(sd.HeaderInOrEmpty("Host"), TStringBuf("1234")); UNIT_ASSERT_VALUES_EQUAL(sd.ServerName(), "1234"); sd.AddHeader("Host", "12345:678"); UNIT_ASSERT_VALUES_EQUAL(sd.HeadersCount(), 3); - UNIT_ASSERT_VALUES_EQUAL(TStringBuf(sd.HeaderIn("Host")), TStringBuf("12345:678")); + UNIT_ASSERT_VALUES_EQUAL(sd.HeaderInOrEmpty("Host"), TStringBuf("12345:678")); UNIT_ASSERT_VALUES_EQUAL(sd.ServerName(), "12345"); UNIT_ASSERT_VALUES_EQUAL(sd.ServerPort(), "678"); } @@ -51,8 +51,8 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) { // This should work UNIT_ASSERT(rd.Parse(" /yandsearch?>a=fake&haha=da HTTP 1.1 OK")); - UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), ">a=fake&haha=da"); - UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), rd.OrigQueryStringBuf()); + UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), ">a=fake&haha=da"); + UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), rd.OrigQuery()); rd.Scan(); UNIT_ASSERT(rd.CgiParam.Has("gta", "fake")); @@ -66,8 +66,8 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) { const TString qs("gta=fake&haha=da"); TServerRequestData rd(qs.c_str()); - UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), qs); - UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), qs); + UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), qs); + UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQuery(), qs); UNIT_ASSERT(rd.CgiParam.Has("gta")); UNIT_ASSERT(rd.CgiParam.Has("haha")); @@ -81,8 +81,8 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) { TServerRequestData rd; rd.Parse(header.c_str()); - UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), qs); - UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), qs); + UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), qs); + UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQuery(), qs); rd.Scan(); UNIT_ASSERT(rd.CgiParam.Has("gta")); @@ -94,8 +94,8 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) { TServerRequestData rd; rd.Parse(" /y#ndsearch?>a=fake&haha=da&uberParam=yes&q=? HTTP 1.1 OK"); - UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), ""); - UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), ""); + UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), ""); + UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQuery(), ""); rd.Scan(); UNIT_ASSERT(rd.CgiParam.empty()); @@ -105,8 +105,8 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) { TServerRequestData rd; rd.Parse(" /yandsearch?#"); - UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), ""); - UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), ""); + UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), ""); + UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQuery(), ""); rd.Scan(); UNIT_ASSERT(rd.CgiParam.empty()); @@ -119,14 +119,14 @@ Y_UNIT_TEST_SUITE(TRequestServerDataTest) { UNIT_ASSERT(rd.CgiParam.Has("gta", "fake")); UNIT_ASSERT(rd.CgiParam.Has("haha", "da")); - UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), qs); - UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), rd.OrigQueryStringBuf()); + UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), qs); + UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), rd.OrigQuery()); constexpr TStringBuf appendix = "gta=true>a=new"; - rd.AppendQueryString(appendix.data(), appendix.size()); + rd.AppendQueryString(appendix); - UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), qs + '&' + appendix); - UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQueryStringBuf(), qs); + UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), qs + '&' + appendix); + UNIT_ASSERT_STRINGS_EQUAL(rd.OrigQuery(), qs); rd.Scan(); diff --git a/library/cpp/http/misc/ya.make b/library/cpp/http/misc/ya.make index fceb3cf79c..7eb4481218 100644 --- a/library/cpp/http/misc/ya.make +++ b/library/cpp/http/misc/ya.make @@ -15,6 +15,7 @@ SRCS( ) PEERDIR( + library/cpp/case_insensitive_string library/cpp/cgiparam library/cpp/digest/lower_case ) |