/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 |