aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/http/io/headers.h
blob: 133adc3ddbb029041ad9610be90235633510a307 (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
#pragma once

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

class IInputStream;
class IOutputStream;

/// @addtogroup Streams_HTTP
/// @{
/// Объект, содержащий информацию о HTTP-заголовке.
class THttpInputHeader {
public:
    /// @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(IInputStream* stream);

    /// Стандартный итератор.
    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_;
};

/// @}