OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/http/http_request_headers.h" | 5 #include "net/http/http_request_headers.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/strings/string_split.h" | 8 #include "base/strings/string_split.h" |
9 #include "base/strings/string_util.h" | 9 #include "base/strings/string_util.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 const char HttpRequestHeaders::kProxyConnection[] = "Proxy-Connection"; | 34 const char HttpRequestHeaders::kProxyConnection[] = "Proxy-Connection"; |
35 const char HttpRequestHeaders::kRange[] = "Range"; | 35 const char HttpRequestHeaders::kRange[] = "Range"; |
36 const char HttpRequestHeaders::kReferer[] = "Referer"; | 36 const char HttpRequestHeaders::kReferer[] = "Referer"; |
37 const char HttpRequestHeaders::kUserAgent[] = "User-Agent"; | 37 const char HttpRequestHeaders::kUserAgent[] = "User-Agent"; |
38 const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding"; | 38 const char HttpRequestHeaders::kTransferEncoding[] = "Transfer-Encoding"; |
39 | 39 |
40 HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair() { | 40 HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair() { |
41 } | 41 } |
42 | 42 |
43 HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair( | 43 HttpRequestHeaders::HeaderKeyValuePair::HeaderKeyValuePair( |
44 const base::StringPiece& key, const base::StringPiece& value) | 44 const base::StringPiece& key, |
| 45 const base::StringPiece& value) |
45 : key(key.data(), key.size()), value(value.data(), value.size()) { | 46 : key(key.data(), key.size()), value(value.data(), value.size()) { |
46 } | 47 } |
47 | 48 |
48 | |
49 HttpRequestHeaders::Iterator::Iterator(const HttpRequestHeaders& headers) | 49 HttpRequestHeaders::Iterator::Iterator(const HttpRequestHeaders& headers) |
50 : started_(false), | 50 : started_(false), |
51 curr_(headers.headers_.begin()), | 51 curr_(headers.headers_.begin()), |
52 end_(headers.headers_.end()) {} | 52 end_(headers.headers_.end()) { |
| 53 } |
53 | 54 |
54 HttpRequestHeaders::Iterator::~Iterator() {} | 55 HttpRequestHeaders::Iterator::~Iterator() { |
| 56 } |
55 | 57 |
56 bool HttpRequestHeaders::Iterator::GetNext() { | 58 bool HttpRequestHeaders::Iterator::GetNext() { |
57 if (!started_) { | 59 if (!started_) { |
58 started_ = true; | 60 started_ = true; |
59 return curr_ != end_; | 61 return curr_ != end_; |
60 } | 62 } |
61 | 63 |
62 if (curr_ == end_) | 64 if (curr_ == end_) |
63 return false; | 65 return false; |
64 | 66 |
65 ++curr_; | 67 ++curr_; |
66 return curr_ != end_; | 68 return curr_ != end_; |
67 } | 69 } |
68 | 70 |
69 HttpRequestHeaders::HttpRequestHeaders() {} | 71 HttpRequestHeaders::HttpRequestHeaders() { |
70 HttpRequestHeaders::~HttpRequestHeaders() {} | 72 } |
| 73 HttpRequestHeaders::~HttpRequestHeaders() { |
| 74 } |
71 | 75 |
72 bool HttpRequestHeaders::GetHeader(const base::StringPiece& key, | 76 bool HttpRequestHeaders::GetHeader(const base::StringPiece& key, |
73 std::string* out) const { | 77 std::string* out) const { |
74 HeaderVector::const_iterator it = FindHeader(key); | 78 HeaderVector::const_iterator it = FindHeader(key); |
75 if (it == headers_.end()) | 79 if (it == headers_.end()) |
76 return false; | 80 return false; |
77 out->assign(it->value); | 81 out->assign(it->value); |
78 return true; | 82 return true; |
79 } | 83 } |
80 | 84 |
(...skipping 18 matching lines...) Expand all Loading... |
99 } | 103 } |
100 | 104 |
101 void HttpRequestHeaders::RemoveHeader(const base::StringPiece& key) { | 105 void HttpRequestHeaders::RemoveHeader(const base::StringPiece& key) { |
102 HeaderVector::iterator it = FindHeader(key); | 106 HeaderVector::iterator it = FindHeader(key); |
103 if (it != headers_.end()) | 107 if (it != headers_.end()) |
104 headers_.erase(it); | 108 headers_.erase(it); |
105 } | 109 } |
106 | 110 |
107 void HttpRequestHeaders::AddHeaderFromString( | 111 void HttpRequestHeaders::AddHeaderFromString( |
108 const base::StringPiece& header_line) { | 112 const base::StringPiece& header_line) { |
109 DCHECK_EQ(std::string::npos, header_line.find("\r\n")) | 113 DCHECK_EQ(std::string::npos, header_line.find("\r\n")) << "\"" << header_line |
110 << "\"" << header_line << "\" contains CRLF."; | 114 << "\" contains CRLF."; |
111 | 115 |
112 const std::string::size_type key_end_index = header_line.find(":"); | 116 const std::string::size_type key_end_index = header_line.find(":"); |
113 if (key_end_index == std::string::npos) { | 117 if (key_end_index == std::string::npos) { |
114 LOG(DFATAL) << "\"" << header_line << "\" is missing colon delimiter."; | 118 LOG(DFATAL) << "\"" << header_line << "\" is missing colon delimiter."; |
115 return; | 119 return; |
116 } | 120 } |
117 | 121 |
118 if (key_end_index == 0) { | 122 if (key_end_index == 0) { |
119 LOG(DFATAL) << "\"" << header_line << "\" is missing header key."; | 123 LOG(DFATAL) << "\"" << header_line << "\" is missing header key."; |
120 return; | 124 return; |
121 } | 125 } |
122 | 126 |
123 const base::StringPiece header_key(header_line.data(), key_end_index); | 127 const base::StringPiece header_key(header_line.data(), key_end_index); |
124 | 128 |
125 const std::string::size_type value_index = key_end_index + 1; | 129 const std::string::size_type value_index = key_end_index + 1; |
126 | 130 |
127 if (value_index < header_line.size()) { | 131 if (value_index < header_line.size()) { |
128 std::string header_value(header_line.data() + value_index, | 132 std::string header_value(header_line.data() + value_index, |
129 header_line.size() - value_index); | 133 header_line.size() - value_index); |
130 std::string::const_iterator header_value_begin = | 134 std::string::const_iterator header_value_begin = header_value.begin(); |
131 header_value.begin(); | 135 std::string::const_iterator header_value_end = header_value.end(); |
132 std::string::const_iterator header_value_end = | |
133 header_value.end(); | |
134 HttpUtil::TrimLWS(&header_value_begin, &header_value_end); | 136 HttpUtil::TrimLWS(&header_value_begin, &header_value_end); |
135 | 137 |
136 if (header_value_begin == header_value_end) { | 138 if (header_value_begin == header_value_end) { |
137 // Value was all LWS. | 139 // Value was all LWS. |
138 SetHeader(header_key, ""); | 140 SetHeader(header_key, ""); |
139 } else { | 141 } else { |
140 SetHeader(header_key, | 142 SetHeader(header_key, |
141 base::StringPiece(&*header_value_begin, | 143 base::StringPiece(&*header_value_begin, |
142 header_value_end - header_value_begin)); | 144 header_value_end - header_value_begin)); |
143 } | 145 } |
144 } else if (value_index == header_line.size()) { | 146 } else if (value_index == header_line.size()) { |
145 SetHeader(header_key, ""); | 147 SetHeader(header_key, ""); |
146 } else { | 148 } else { |
147 NOTREACHED(); | 149 NOTREACHED(); |
148 } | 150 } |
149 } | 151 } |
150 | 152 |
151 void HttpRequestHeaders::AddHeadersFromString( | 153 void HttpRequestHeaders::AddHeadersFromString( |
152 const base::StringPiece& headers) { | 154 const base::StringPiece& headers) { |
153 // TODO(willchan): Consider adding more StringPiece support in string_util.h | 155 // TODO(willchan): Consider adding more StringPiece support in string_util.h |
154 // to eliminate copies. | 156 // to eliminate copies. |
155 std::vector<std::string> header_line_vector; | 157 std::vector<std::string> header_line_vector; |
156 base::SplitStringUsingSubstr(headers.as_string(), "\r\n", | 158 base::SplitStringUsingSubstr( |
157 &header_line_vector); | 159 headers.as_string(), "\r\n", &header_line_vector); |
158 for (std::vector<std::string>::const_iterator it = header_line_vector.begin(); | 160 for (std::vector<std::string>::const_iterator it = header_line_vector.begin(); |
159 it != header_line_vector.end(); ++it) { | 161 it != header_line_vector.end(); |
| 162 ++it) { |
160 if (!it->empty()) | 163 if (!it->empty()) |
161 AddHeaderFromString(*it); | 164 AddHeaderFromString(*it); |
162 } | 165 } |
163 } | 166 } |
164 | 167 |
165 void HttpRequestHeaders::MergeFrom(const HttpRequestHeaders& other) { | 168 void HttpRequestHeaders::MergeFrom(const HttpRequestHeaders& other) { |
166 for (HeaderVector::const_iterator it = other.headers_.begin(); | 169 for (HeaderVector::const_iterator it = other.headers_.begin(); |
167 it != other.headers_.end(); ++it ) { | 170 it != other.headers_.end(); |
| 171 ++it) { |
168 SetHeader(it->key, it->value); | 172 SetHeader(it->key, it->value); |
169 } | 173 } |
170 } | 174 } |
171 | 175 |
172 std::string HttpRequestHeaders::ToString() const { | 176 std::string HttpRequestHeaders::ToString() const { |
173 std::string output; | 177 std::string output; |
174 for (HeaderVector::const_iterator it = headers_.begin(); | 178 for (HeaderVector::const_iterator it = headers_.begin(); it != headers_.end(); |
175 it != headers_.end(); ++it) { | 179 ++it) { |
176 if (!it->value.empty()) { | 180 if (!it->value.empty()) { |
177 base::StringAppendF(&output, "%s: %s\r\n", | 181 base::StringAppendF( |
178 it->key.c_str(), it->value.c_str()); | 182 &output, "%s: %s\r\n", it->key.c_str(), it->value.c_str()); |
179 } else { | 183 } else { |
180 base::StringAppendF(&output, "%s:\r\n", it->key.c_str()); | 184 base::StringAppendF(&output, "%s:\r\n", it->key.c_str()); |
181 } | 185 } |
182 } | 186 } |
183 output.append("\r\n"); | 187 output.append("\r\n"); |
184 return output; | 188 return output; |
185 } | 189 } |
186 | 190 |
187 base::Value* HttpRequestHeaders::NetLogCallback( | 191 base::Value* HttpRequestHeaders::NetLogCallback( |
188 const std::string* request_line, | 192 const std::string* request_line, |
189 NetLog::LogLevel log_level) const { | 193 NetLog::LogLevel log_level) const { |
190 base::DictionaryValue* dict = new base::DictionaryValue(); | 194 base::DictionaryValue* dict = new base::DictionaryValue(); |
191 dict->SetString("line", *request_line); | 195 dict->SetString("line", *request_line); |
192 base::ListValue* headers = new base::ListValue(); | 196 base::ListValue* headers = new base::ListValue(); |
193 for (HeaderVector::const_iterator it = headers_.begin(); | 197 for (HeaderVector::const_iterator it = headers_.begin(); it != headers_.end(); |
194 it != headers_.end(); ++it) { | 198 ++it) { |
195 std::string log_value = ElideHeaderValueForNetLog( | 199 std::string log_value = |
196 log_level, it->key, it->value); | 200 ElideHeaderValueForNetLog(log_level, it->key, it->value); |
197 headers->Append(new base::StringValue( | 201 headers->Append(new base::StringValue( |
198 base::StringPrintf("%s: %s", | 202 base::StringPrintf("%s: %s", it->key.c_str(), log_value.c_str()))); |
199 it->key.c_str(), log_value.c_str()))); | |
200 } | 203 } |
201 dict->Set("headers", headers); | 204 dict->Set("headers", headers); |
202 return dict; | 205 return dict; |
203 } | 206 } |
204 | 207 |
205 // static | 208 // static |
206 bool HttpRequestHeaders::FromNetLogParam(const base::Value* event_param, | 209 bool HttpRequestHeaders::FromNetLogParam(const base::Value* event_param, |
207 HttpRequestHeaders* headers, | 210 HttpRequestHeaders* headers, |
208 std::string* request_line) { | 211 std::string* request_line) { |
209 headers->Clear(); | 212 headers->Clear(); |
210 *request_line = ""; | 213 *request_line = ""; |
211 | 214 |
212 const base::DictionaryValue* dict = NULL; | 215 const base::DictionaryValue* dict = NULL; |
213 const base::ListValue* header_list = NULL; | 216 const base::ListValue* header_list = NULL; |
214 | 217 |
215 if (!event_param || | 218 if (!event_param || !event_param->GetAsDictionary(&dict) || |
216 !event_param->GetAsDictionary(&dict) || | |
217 !dict->GetList("headers", &header_list) || | 219 !dict->GetList("headers", &header_list) || |
218 !dict->GetString("line", request_line)) { | 220 !dict->GetString("line", request_line)) { |
219 return false; | 221 return false; |
220 } | 222 } |
221 | 223 |
222 for (base::ListValue::const_iterator it = header_list->begin(); | 224 for (base::ListValue::const_iterator it = header_list->begin(); |
223 it != header_list->end(); | 225 it != header_list->end(); |
224 ++it) { | 226 ++it) { |
225 std::string header_line; | 227 std::string header_line; |
226 if (!(*it)->GetAsString(&header_line)) { | 228 if (!(*it)->GetAsString(&header_line)) { |
227 headers->Clear(); | 229 headers->Clear(); |
228 *request_line = ""; | 230 *request_line = ""; |
229 return false; | 231 return false; |
230 } | 232 } |
231 headers->AddHeaderFromString(header_line); | 233 headers->AddHeaderFromString(header_line); |
232 } | 234 } |
233 return true; | 235 return true; |
234 } | 236 } |
235 | 237 |
236 HttpRequestHeaders::HeaderVector::iterator | 238 HttpRequestHeaders::HeaderVector::iterator HttpRequestHeaders::FindHeader( |
237 HttpRequestHeaders::FindHeader(const base::StringPiece& key) { | 239 const base::StringPiece& key) { |
238 for (HeaderVector::iterator it = headers_.begin(); | 240 for (HeaderVector::iterator it = headers_.begin(); it != headers_.end(); |
239 it != headers_.end(); ++it) { | 241 ++it) { |
240 if (key.length() == it->key.length() && | 242 if (key.length() == it->key.length() && |
241 !base::strncasecmp(key.data(), it->key.data(), key.length())) | 243 !base::strncasecmp(key.data(), it->key.data(), key.length())) |
242 return it; | 244 return it; |
243 } | 245 } |
244 | 246 |
245 return headers_.end(); | 247 return headers_.end(); |
246 } | 248 } |
247 | 249 |
248 HttpRequestHeaders::HeaderVector::const_iterator | 250 HttpRequestHeaders::HeaderVector::const_iterator HttpRequestHeaders::FindHeader( |
249 HttpRequestHeaders::FindHeader(const base::StringPiece& key) const { | 251 const base::StringPiece& key) const { |
250 for (HeaderVector::const_iterator it = headers_.begin(); | 252 for (HeaderVector::const_iterator it = headers_.begin(); it != headers_.end(); |
251 it != headers_.end(); ++it) { | 253 ++it) { |
252 if (key.length() == it->key.length() && | 254 if (key.length() == it->key.length() && |
253 !base::strncasecmp(key.data(), it->key.data(), key.length())) | 255 !base::strncasecmp(key.data(), it->key.data(), key.length())) |
254 return it; | 256 return it; |
255 } | 257 } |
256 | 258 |
257 return headers_.end(); | 259 return headers_.end(); |
258 } | 260 } |
259 | 261 |
260 } // namespace net | 262 } // namespace net |
OLD | NEW |