aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http/io/headers.cpp
blob: 5d0d4f895d56309c0f3933a2319788a1cf8ace25 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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); 
}