Coverage Report

Created: 2024-09-11 06:42

/src/brpc/src/brpc/http_header.cpp
Line
Count
Source (jump to first uncovered line)
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
19
#include "brpc/http_status_code.h"     // HTTP_STATUS_*
20
#include "brpc/http_header.h"
21
22
23
namespace brpc {
24
25
const char* HttpHeader::SET_COOKIE = "set-cookie";
26
const char* HttpHeader::COOKIE = "cookie";
27
const char* HttpHeader::CONTENT_TYPE = "content-type";
28
29
HttpHeader::HttpHeader() 
30
    : _status_code(HTTP_STATUS_OK)
31
    , _method(HTTP_METHOD_GET)
32
    , _version(1, 1)
33
8.43k
    , _first_set_cookie(NULL) {
34
8.43k
    CHECK_EQ(0, _headers.init(29));
35
    // NOTE: don't forget to clear the field in Clear() as well.
36
8.43k
}
37
38
0
void HttpHeader::Swap(HttpHeader &rhs) {
39
0
    _headers.swap(rhs._headers);
40
0
    _uri.Swap(rhs._uri);
41
0
    std::swap(_status_code, rhs._status_code);
42
0
    std::swap(_method, rhs._method);
43
0
    _content_type.swap(rhs._content_type);
44
0
    _unresolved_path.swap(rhs._unresolved_path);
45
0
    std::swap(_version, rhs._version);
46
0
}
47
48
0
void HttpHeader::Clear() {
49
0
    _headers.clear();
50
0
    _uri.Clear();
51
0
    _status_code = HTTP_STATUS_OK;
52
0
    _method = HTTP_METHOD_GET;
53
0
    _content_type.clear();
54
0
    _unresolved_path.clear();
55
0
    _version = std::make_pair(1, 1);
56
0
}
57
58
10.7k
const std::string* HttpHeader::GetHeader(const char* key) const {
59
10.7k
    return GetHeader(std::string(key));
60
10.7k
}
61
62
10.7k
const std::string* HttpHeader::GetHeader(const std::string& key) const {
63
10.7k
    if (IsSetCookie(key)) {
64
0
        return _first_set_cookie;
65
0
    }
66
10.7k
    std::string* val = _headers.seek(key);
67
10.7k
    return val;
68
10.7k
}
69
70
0
std::vector<const std::string*> HttpHeader::GetAllSetCookieHeader() const {
71
0
    return GetMultiLineHeaders(SET_COOKIE);
72
0
}
73
74
std::vector<const std::string*>
75
0
HttpHeader::GetMultiLineHeaders(const std::string& key) const {
76
0
    std::vector<const std::string*> headers;
77
0
    for (const auto& iter : _headers) {
78
0
        if (_header_key_equal(iter.first, key)) {
79
0
            headers.push_back(&iter.second);
80
0
        }
81
0
    }
82
0
    return headers;
83
0
}
84
85
void HttpHeader::SetHeader(const std::string& key,
86
0
                           const std::string& value) {
87
0
    GetOrAddHeader(key) = value;
88
0
}
89
90
0
void HttpHeader::RemoveHeader(const char* key) {
91
0
    if (IsContentType(key)) {
92
0
        _content_type.clear();
93
0
    } else {
94
0
        _headers.erase(key);
95
0
        if (IsSetCookie(key)) {
96
0
            _first_set_cookie = NULL;
97
0
        }
98
0
    }
99
0
}
100
101
void HttpHeader::AppendHeader(const std::string& key,
102
0
    const butil::StringPiece& value) {
103
0
    if (!CanFoldedInLine(key)) {
104
        // Add a new Set-Cookie header field.
105
0
        std::string& slot = AddHeader(key);
106
0
        slot.assign(value.data(), value.size());
107
0
    } else {
108
0
        std::string& slot = GetOrAddHeader(key);
109
0
        if (slot.empty()) {
110
0
            slot.assign(value.data(), value.size());
111
0
        } else {
112
0
            slot.reserve(slot.size() + 1 + value.size());
113
0
            slot.append(HeaderValueDelimiter(key));
114
0
            slot.append(value.data(), value.size());
115
0
        }
116
0
    }
117
0
}
118
119
0
const char* HttpHeader::reason_phrase() const {
120
0
    return HttpReasonPhrase(_status_code);
121
0
}
122
    
123
15.1k
void HttpHeader::set_status_code(int status_code) {
124
15.1k
    _status_code = status_code;
125
15.1k
}
126
127
29.6k
std::string& HttpHeader::GetOrAddHeader(const std::string& key) {
128
29.6k
    if (IsContentType(key)) {
129
192
        return _content_type;
130
192
    }
131
132
29.4k
    bool is_set_cookie = IsSetCookie(key);
133
    // Only returns the first Set-Cookie header field for compatibility.
134
29.4k
    if (is_set_cookie && NULL != _first_set_cookie) {
135
0
        return *_first_set_cookie;
136
0
    }
137
138
29.4k
    std::string* val = _headers.seek(key);
139
29.4k
    if (NULL == val) {
140
21.0k
        val = _headers.insert({ key, "" });
141
21.0k
        if (is_set_cookie) {
142
0
            _first_set_cookie = val;
143
0
        }
144
21.0k
    }
145
29.4k
    return *val;
146
29.4k
}
147
148
1.73k
std::string& HttpHeader::AddHeader(const std::string& key) {
149
1.73k
    std::string* val = _headers.insert({ key, "" });
150
1.73k
    if (IsSetCookie(key) && NULL == _first_set_cookie) {
151
148
        _first_set_cookie = val;
152
148
    }
153
1.73k
    return *val;
154
1.73k
}
155
156
0
const HttpHeader& DefaultHttpHeader() {
157
0
    static HttpHeader h;
158
0
    return h;
159
0
}
160
161
} // namespace brpc