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