aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http/io/headers.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/io/headers.cpp
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'library/cpp/http/io/headers.cpp')
-rw-r--r--library/cpp/http/io/headers.cpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/library/cpp/http/io/headers.cpp b/library/cpp/http/io/headers.cpp
new file mode 100644
index 0000000000..4ec27a29e8
--- /dev/null
+++ b/library/cpp/http/io/headers.cpp
@@ -0,0 +1,108 @@
+#include "headers.h"
+#include "stream.h"
+
+#include <util/generic/strbuf.h>
+#include <util/generic/yexception.h>
+#include <util/stream/output.h>
+#include <util/string/ascii.h>
+#include <util/string/cast.h>
+#include <util/string/strip.h>
+
+static inline TStringBuf Trim(const char* b, const char* e) noexcept {
+ return StripString(TStringBuf(b, e));
+}
+
+THttpInputHeader::THttpInputHeader(const TStringBuf header) {
+ size_t pos = header.find(':');
+
+ if (pos == TString::npos) {
+ ythrow THttpParseException() << "can not parse http header(" << TString{header}.Quote() << ")";
+ }
+
+ Name_ = TString(header.cbegin(), header.cbegin() + pos);
+ Value_ = ::ToString(Trim(header.cbegin() + pos + 1, header.cend()));
+}
+
+THttpInputHeader::THttpInputHeader(TString name, TString value)
+ : Name_(std::move(name))
+ , Value_(std::move(value))
+{
+}
+
+void THttpInputHeader::OutTo(IOutputStream* stream) const {
+ typedef IOutputStream::TPart TPart;
+
+ const TPart parts[] = {
+ TPart(Name_),
+ TPart(": ", 2),
+ TPart(Value_),
+ TPart::CrLf(),
+ };
+
+ stream->Write(parts, sizeof(parts) / sizeof(*parts));
+}
+
+THttpHeaders::THttpHeaders(IInputStream* stream) {
+ TString header;
+ TString line;
+
+ bool rdOk = stream->ReadLine(header);
+ while (rdOk && !header.empty()) {
+ rdOk = stream->ReadLine(line);
+
+ if (rdOk && ((line[0] == ' ') || (line[0] == '\t'))) {
+ header += line;
+ } else {
+ AddHeader(THttpInputHeader(header));
+ header = line;
+ }
+ }
+}
+
+bool THttpHeaders::HasHeader(const TStringBuf header) const {
+ return FindHeader(header);
+}
+
+const THttpInputHeader* THttpHeaders::FindHeader(const TStringBuf header) const {
+ for (const auto& hdr : Headers_) {
+ if (AsciiCompareIgnoreCase(hdr.Name(), header) == 0) {
+ return &hdr;
+ }
+ }
+ return nullptr;
+}
+
+void THttpHeaders::RemoveHeader(const TStringBuf header) {
+ for (auto h = Headers_.begin(); h != Headers_.end(); ++h) {
+ if (AsciiCompareIgnoreCase(h->Name(), header) == 0) {
+ Headers_.erase(h);
+ return;
+ }
+ }
+}
+
+void THttpHeaders::AddOrReplaceHeader(const THttpInputHeader& header) {
+ for (auto& hdr : Headers_) {
+ if (AsciiCompareIgnoreCase(hdr.Name(), header.Name()) == 0) {
+ hdr = header;
+ return;
+ }
+ }
+
+ AddHeader(header);
+}
+
+void THttpHeaders::AddHeader(THttpInputHeader header) {
+ Headers_.push_back(std::move(header));
+}
+
+void THttpHeaders::OutTo(IOutputStream* stream) const {
+ for (TConstIterator header = Begin(); header != End(); ++header) {
+ header->OutTo(stream);
+ }
+}
+
+template <>
+void Out<THttpHeaders>(IOutputStream& out, const THttpHeaders& h) {
+ h.OutTo(&out);
+}