aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http/io/headers.h
blob: 72d3dec4bb0c8818feac88ff550b37a05a576b6e (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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#pragma once

#include <util/generic/array_ref.h>
#include <util/generic/deque.h>
#include <util/generic/string.h>
#include <util/generic/strbuf.h>
#include <util/string/cast.h>

class IInputStream;
class IOutputStream;

/// @addtogroup Streams_HTTP
/// @{
/// Объект, содержащий информацию о HTTP-заголовке.
class THttpInputHeader {
public:
    THttpInputHeader() = delete;
    THttpInputHeader(const THttpInputHeader&) = default;
    THttpInputHeader(THttpInputHeader&&) = default;
    THttpInputHeader& operator=(const THttpInputHeader&) = default;
    THttpInputHeader& operator=(THttpInputHeader&&) = default;

    /// @param[in] header - строка вида 'параметр: значение'.
    THttpInputHeader(TStringBuf header);
    /// @param[in] name - имя параметра.
    /// @param[in] value - значение параметра.
    THttpInputHeader(TString name, TString value);

    /// Возвращает имя параметра.
    inline const TString& Name() const noexcept {
        return Name_;
    }

    /// Возвращает значение параметра.
    inline const TString& Value() const noexcept {
        return Value_;
    }

    /// Записывает заголовок вида "имя параметра: значение\r\n" в поток.
    void OutTo(IOutputStream* stream) const;

    /// Возвращает строку "имя параметра: значение".
    inline TString ToString() const {
        return Name_ + TStringBuf(": ") + Value_;
    }

private:
    TString Name_;
    TString Value_;
};

/// Контейнер для хранения HTTP-заголовков
class THttpHeaders {
    using THeaders = TDeque<THttpInputHeader>;

public:
    using TConstIterator = THeaders::const_iterator;

    THttpHeaders() = default;
    THttpHeaders(const THttpHeaders&) = default;
    THttpHeaders& operator=(const THttpHeaders&) = default;
    THttpHeaders(THttpHeaders&&) = default;
    THttpHeaders& operator=(THttpHeaders&&) = default;

    /// Добавляет каждую строку из потока в контейнер, считая ее правильным заголовком.
    THttpHeaders(IInputStream* stream);

    /// Создаёт контейнер из initializer-list'а или массива/вектора хедеров.
    /// Пример: `THttpHeaders headers({{"Host", "example.com"}});`
    THttpHeaders(TArrayRef<const THttpInputHeader> headers);

    /// Стандартный итератор.
    inline TConstIterator Begin() const noexcept {
        return Headers_.begin();
    }
    inline TConstIterator begin() const noexcept {
        return Headers_.begin();
    }

    /// Стандартный итератор.
    inline TConstIterator End() const noexcept {
        return Headers_.end();
    }
    inline TConstIterator end() const noexcept {
        return Headers_.end();
    }

    /// Возвращает количество заголовков в контейнере.
    inline size_t Count() const noexcept {
        return Headers_.size();
    }

    /// Проверяет, содержит ли контейнер хотя бы один заголовок.
    inline bool Empty() const noexcept {
        return Headers_.empty();
    }

    /// Добавляет заголовок в контейнер.
    void AddHeader(THttpInputHeader header);

    template <typename ValueType>
    void AddHeader(TString name, const ValueType& value) {
        AddHeader(THttpInputHeader(std::move(name), ToString(value)));
    }

    /// Добавляет заголовок в контейнер, если тот не содержит заголовка
    /// c таким же параметром. В противном случае, заменяет существующий
    /// заголовок на новый.
    void AddOrReplaceHeader(const THttpInputHeader& header);

    template <typename ValueType>
    void AddOrReplaceHeader(TString name, const ValueType& value) {
        AddOrReplaceHeader(THttpInputHeader(std::move(name), ToString(value)));
    }

    // Проверяет, есть ли такой заголовок
    bool HasHeader(TStringBuf header) const;

    /// Удаляет заголовок, если он есть.
    void RemoveHeader(TStringBuf header);

    /// Ищет заголовок по указанному имени
    /// Возвращает nullptr, если не нашел
    const THttpInputHeader* FindHeader(TStringBuf header) const;

    /// Записывает все заголовки контейнера в поток.
    /// @details Каждый заголовк записывается в виде "имя параметра: значение\r\n".
    void OutTo(IOutputStream* stream) const;

    /// Обменивает наборы заголовков двух контейнеров.
    void Swap(THttpHeaders& headers) noexcept {
        Headers_.swap(headers.Headers_);
    }

private:
    THeaders Headers_;
};

/// @}