aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http/misc
diff options
context:
space:
mode:
authorarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-02-17 12:04:09 +0300
committerarcadia-devtools <arcadia-devtools@yandex-team.ru>2022-02-17 12:04:09 +0300
commit2c8e314f8fff8633fe2cf026badfbf6180845ae0 (patch)
treec3b650d13934ec1315e3660d60fd2275f09b03a7 /library/cpp/http/misc
parenta49ae9d891c35087b242c854f69880fd9fecbddd (diff)
downloadydb-2c8e314f8fff8633fe2cf026badfbf6180845ae0.tar.gz
intermediate changes
ref:d5f945ecdc1f5af1ad57e12787c6b8ed1a9f0f12
Diffstat (limited to 'library/cpp/http/misc')
-rw-r--r--library/cpp/http/misc/httpreqdata.cpp211
-rw-r--r--library/cpp/http/misc/httpreqdata.h81
-rw-r--r--library/cpp/http/misc/httpreqdata_ut.cpp42
-rw-r--r--library/cpp/http/misc/ya.make1
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?&gta=fake&haha=da HTTP 1.1 OK"));
- UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), "&gta=fake&haha=da");
- UNIT_ASSERT_STRINGS_EQUAL(rd.QueryStringBuf(), rd.OrigQueryStringBuf());
+ UNIT_ASSERT_STRINGS_EQUAL(rd.Query(), "&gta=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?&gta=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&gta=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
)