aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http/misc/httpreqdata.cpp
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /library/cpp/http/misc/httpreqdata.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/http/misc/httpreqdata.cpp')
-rw-r--r--library/cpp/http/misc/httpreqdata.cpp196
1 files changed, 196 insertions, 0 deletions
diff --git a/library/cpp/http/misc/httpreqdata.cpp b/library/cpp/http/misc/httpreqdata.cpp
new file mode 100644
index 0000000000..f6951f68cd
--- /dev/null
+++ b/library/cpp/http/misc/httpreqdata.cpp
@@ -0,0 +1,196 @@
+#include "httpreqdata.h"
+
+#include <util/stream/mem.h>
+
+TBaseServerRequestData::TBaseServerRequestData(SOCKET s)
+ : Addr(nullptr)
+ , Host()
+ , Port()
+ , Path(nullptr)
+ , Search(nullptr)
+ , SearchLength(0)
+ , 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())
+{
+}
+
+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::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;
+}
+
+const char* TBaseServerRequestData::RemoteAddr() const {
+ if (!Addr) {
+ *AddrData = 0;
+ GetRemoteAddr(Socket, AddrData, sizeof(AddrData));
+ Addr = AddrData;
+ }
+
+ return Addr;
+}
+
+const char* TBaseServerRequestData::HeaderIn(TStringBuf key) const {
+ auto it = HeadersIn_.find(key);
+
+ if (it == HeadersIn_.end()) {
+ return nullptr;
+ }
+
+ return it->second.data();
+}
+
+TString TBaseServerRequestData::HeaderByIndex(size_t n) const noexcept {
+ if (n >= HeadersCount()) {
+ return nullptr;
+ }
+
+ THttpHeadersContainer::const_iterator i = HeadersIn_.begin();
+
+ while (n) {
+ ++i;
+ --n;
+ }
+
+ return TString(i->first) + TStringBuf(": ") + i->second;
+}
+
+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) {
+ return ScriptName();
+ }
+ return nullptr;
+}
+
+void TBaseServerRequestData::Clear() {
+ HeadersIn_.clear();
+ Addr = Path = Search = nullptr;
+ OrigSearch = {};
+ SearchLength = 0;
+ 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;
+ }
+ CurPage += Path;
+ if (Search) {
+ CurPage += '?';
+ CurPage += Search;
+ }
+ }
+ return CurPage.data();
+}
+
+bool TBaseServerRequestData::Parse(const char* origReq) {
+ size_t origReqLength = strlen(origReq);
+ ParseBuf.Assign(origReq, origReqLength + 1);
+ char* req = ParseBuf.Data();
+
+ while (*req == ' ' || *req == '\t')
+ req++;
+ if (*req != '/')
+ return false; // we are not a proxy
+ while (req[1] == '/') // remove redundant slashes
+ req++;
+
+ // detect url end (can contain some garbage after whitespace, e.g. 'HTTP 1.1')
+ char* urlEnd = req;
+ while (*urlEnd && *urlEnd != ' ' && *urlEnd != '\t')
+ urlEnd++;
+ if (*urlEnd)
+ *urlEnd = 0;
+
+ // cut fragment if exists
+ char* fragment = strchr(req, '#');
+ if (fragment)
+ *fragment = 0; // ignore fragment
+ else
+ fragment = urlEnd;
+ Path = req;
+
+ // calculate Search length without additional strlen-ing
+ Search = strchr(Path, '?');
+ if (Search) {
+ *Search++ = 0;
+ ptrdiff_t delta = fragment - Search;
+ // indeed, second case is a parse error
+ SearchLength = (delta >= 0) ? delta : (urlEnd - Search);
+ Y_ASSERT(strlen(Search) == SearchLength);
+ } else {
+ SearchLength = 0;
+ }
+ OrigSearch = {Search, SearchLength};
+
+ return true;
+}
+
+void TBaseServerRequestData::AddHeader(const TString& name, const TString& value) {
+ HeadersIn_[name] = 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);
+ }
+}
+
+void TBaseServerRequestData::SetPath(const TString& path) {
+ PathStorage = TBuffer(path.data(), path.size() + 1);
+ Path = PathStorage.Data();
+}