13345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The rules for header parsing were borrowed from Firefox: 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpResponseHead.cpp 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The rules for parsing content-types were also borrowed from Firefox: 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_response_headers.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm> 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/metrics/histogram.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/pickle.h" 173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_number_conversions.h" 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h" 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h" 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/escape.h" 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_util.h" 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::Time; 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottusing base::TimeDelta; 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//----------------------------------------------------------------------------- 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// These headers are RFC 2616 hop-by-hop headers; 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// not to be stored by caches. 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char* const kHopByHopResponseHeaders[] = { 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "connection", 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "proxy-connection", 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "keep-alive", 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "trailer", 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "transfer-encoding", 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "upgrade" 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// These headers are challenge response headers; 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// not to be stored by caches. 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char* const kChallengeResponseHeaders[] = { 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "www-authenticate", 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "proxy-authenticate" 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// These headers are cookie setting headers; 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// not to be stored by caches or disclosed otherwise. 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char* const kCookieResponseHeaders[] = { 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "set-cookie", 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "set-cookie2" 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// These response headers are not copied from a 304/206 response to the cached 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// response headers. This list is based on Mozilla's nsHttpResponseHead.cpp. 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst char* const kNonUpdatedHeaders[] = { 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "connection", 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "proxy-connection", 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "keep-alive", 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "www-authenticate", 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "proxy-authenticate", 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "trailer", 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "transfer-encoding", 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "upgrade", 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // these should never change: 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "content-location", 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "content-md5", 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "etag", 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // assume cache-control: no-transform 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "content-encoding", 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "content-range", 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "content-type", 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // some broken microsoft servers send 'content-length: 0' with 304s 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "content-length" 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool ShouldUpdateHeader(const std::string::const_iterator& name_begin, 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string::const_iterator& name_end) { 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < arraysize(kNonUpdatedHeaders); ++i) { 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (LowerCaseEqualsASCII(name_begin, name_end, kNonUpdatedHeaders[i])) 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Functions for histogram initialization. The code 0 is put in the 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// response map to track response codes that are invalid. 9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// TODO(gavinp): Greatly prune the collected codes once we learn which 9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// ones are not sent in practice, to reduce upload size & memory use. 9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenenum { 9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HISTOGRAM_MIN_HTTP_RESPONSE_CODE = 100, 9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HISTOGRAM_MAX_HTTP_RESPONSE_CODE = 599, 9772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 9872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstd::vector<int> GetAllHttpResponseCodes() { 10072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::vector<int> codes; 10172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen codes.reserve( 10272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen HISTOGRAM_MAX_HTTP_RESPONSE_CODE - HISTOGRAM_MIN_HTTP_RESPONSE_CODE + 2); 10372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen codes.push_back(0); 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (int i = HISTOGRAM_MIN_HTTP_RESPONSE_CODE; 10572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen i <= HISTOGRAM_MAX_HTTP_RESPONSE_CODE; ++i) 10672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen codes.push_back(i); 10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return codes; 10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint MapHttpResponseCode(int code) { 11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (HISTOGRAM_MIN_HTTP_RESPONSE_CODE <= code && 11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen code <= HISTOGRAM_MAX_HTTP_RESPONSE_CODE) 11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return code; 11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return 0; 11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstruct HttpResponseHeaders::ParsedHeader { 12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // A header "continuation" contains only a subsequent value for the 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // preceding header. (Header values are comma separated.) 12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool is_continuation() const { return name_begin == name_end; } 12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string::const_iterator name_begin; 12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string::const_iterator name_end; 12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string::const_iterator value_begin; 12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string::const_iterator value_end; 12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}; 12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//----------------------------------------------------------------------------- 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpResponseHeaders::HttpResponseHeaders(const std::string& raw_input) 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : response_code_(-1) { 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Parse(raw_input); 13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The most important thing to do with this histogram is find out 13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // the existence of unusual HTTP response codes. As it happens 13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // right now, there aren't double-constructions of response headers 13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // using this constructor, so our counts should also be accurate, 14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // without instantiating the histogram in two places. It is also 14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // important that this histogram not collect data in the other 14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // constructor, which rebuilds an histogram from a pickle, since 14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // that would actually create a double call between the original 14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // HttpResponseHeader that was serialized, and initialization of the 14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // new object from that pickle. 14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.HttpResponseCode", 14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MapHttpResponseCode(response_code_), 14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Note the third argument is only 14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // evaluated once, see macro 15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // definition for details. 15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GetAllHttpResponseCodes()); 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpResponseHeaders::HttpResponseHeaders(const Pickle& pickle, void** iter) 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : response_code_(-1) { 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string raw_input; 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pickle.ReadString(iter, &raw_input)) 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Parse(raw_input); 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::Persist(Pickle* pickle, PersistOptions options) { 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (options == PERSIST_RAW) { 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pickle->WriteString(raw_headers_); 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; // Done. 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderSet filter_headers; 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Construct set of headers to filter out based on options. 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((options & PERSIST_SANS_NON_CACHEABLE) == PERSIST_SANS_NON_CACHEABLE) 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddNonCacheableHeaders(&filter_headers); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((options & PERSIST_SANS_COOKIES) == PERSIST_SANS_COOKIES) 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddCookieHeaders(&filter_headers); 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((options & PERSIST_SANS_CHALLENGES) == PERSIST_SANS_CHALLENGES) 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddChallengeHeaders(&filter_headers); 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((options & PERSIST_SANS_HOP_BY_HOP) == PERSIST_SANS_HOP_BY_HOP) 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddHopByHopHeaders(&filter_headers); 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((options & PERSIST_SANS_RANGES) == PERSIST_SANS_RANGES) 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddHopContentRangeHeaders(&filter_headers); 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string blob; 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott blob.reserve(raw_headers_.size()); 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This copies the status line w/ terminator null. 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note raw_headers_ has embedded nulls instead of \n, 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // so this just copies the first header line. 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott blob.assign(raw_headers_.c_str(), strlen(raw_headers_.c_str()) + 1); 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < parsed_.size(); ++i) { 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!parsed_[i].is_continuation()); 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Locate the start of the next header. 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t k = i; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (++k < parsed_.size() && parsed_[k].is_continuation()) {} 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --k; 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string header_name(parsed_[i].name_begin, parsed_[i].name_end); 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StringToLowerASCII(&header_name); 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (filter_headers.find(header_name) == filter_headers.end()) { 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make sure there is a null after the value. 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott blob.append(parsed_[i].name_begin, parsed_[k].value_end); 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott blob.push_back('\0'); 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i = k; 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott blob.push_back('\0'); 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott pickle->WriteString(blob); 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::Update(const HttpResponseHeaders& new_headers) { 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(new_headers.response_code() == 304 || 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_headers.response_code() == 206); 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Copy up to the null byte. This just copies the status line. 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string new_raw_headers(raw_headers_.c_str()); 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.push_back('\0'); 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderSet updated_headers; 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // NOTE: we write the new headers then the old headers for convenience. The 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // order should not matter. 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Figure out which headers we want to take from new_headers: 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < new_headers.parsed_.size(); ++i) { 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderList& new_parsed = new_headers.parsed_; 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!new_parsed[i].is_continuation()); 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Locate the start of the next header. 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t k = i; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (++k < new_parsed.size() && new_parsed[k].is_continuation()) {} 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --k; 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string::const_iterator& name_begin = new_parsed[i].name_begin; 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string::const_iterator& name_end = new_parsed[i].name_end; 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ShouldUpdateHeader(name_begin, name_end)) { 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string name(name_begin, name_end); 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StringToLowerASCII(&name); 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott updated_headers.insert(name); 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Preserve this header line in the merged result, making sure there is 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a null after the value. 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.append(name_begin, new_parsed[k].value_end); 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.push_back('\0'); 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i = k; 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Now, build the new raw headers. 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MergeWithHeaders(new_raw_headers, updated_headers); 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers, 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HeaderSet& headers_to_remove) { 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string new_raw_headers(raw_headers); 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < parsed_.size(); ++i) { 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!parsed_[i].is_continuation()); 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Locate the start of the next header. 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t k = i; 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (++k < parsed_.size() && parsed_[k].is_continuation()) {} 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --k; 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string name(parsed_[i].name_begin, parsed_[i].name_end); 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StringToLowerASCII(&name); 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (headers_to_remove.find(name) == headers_to_remove.end()) { 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // It's ok to preserve this header in the final result. 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end); 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.push_back('\0'); 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i = k; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.push_back('\0'); 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make this object hold the new data. 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.clear(); 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_.clear(); 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Parse(new_raw_headers); 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::RemoveHeader(const std::string& name) { 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Copy up to the null byte. This just copies the status line. 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string new_raw_headers(raw_headers_.c_str()); 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.push_back('\0'); 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string lowercase_name(name); 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StringToLowerASCII(&lowercase_name); 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderSet to_remove; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott to_remove.insert(lowercase_name); 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MergeWithHeaders(new_raw_headers, to_remove); 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::AddHeader(const std::string& header) { 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]); 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]); 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Don't copy the last null. 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string new_raw_headers(raw_headers_, 0, raw_headers_.size() - 1); 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.append(header); 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.push_back('\0'); 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.push_back('\0'); 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make this object hold the new data. 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.clear(); 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_.clear(); 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Parse(new_raw_headers); 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::ReplaceStatusLine(const std::string& new_status) { 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Copy up to the null byte. This just copies the status line. 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string new_raw_headers(new_status); 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott new_raw_headers.push_back('\0'); 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeaderSet empty_to_remove; 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MergeWithHeaders(new_raw_headers, empty_to_remove); 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::Parse(const std::string& raw_input) { 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.reserve(raw_input.size()); 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ParseStatusLine adds a normalized status line to raw_headers_ 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator line_begin = raw_input.begin(); 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator line_end = 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott find(line_begin, raw_input.end(), '\0'); 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // has_headers = true, if there is any data following the status line. 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Used by ParseStatusLine() to decide if a HTTP/0.9 is really a HTTP/1.0. 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool has_headers = (line_end != raw_input.end() && 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (line_end + 1) != raw_input.end() && 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *(line_end + 1) != '\0'); 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ParseStatusLine(line_begin, line_end, has_headers); 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (line_end == raw_input.end()) { 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.push_back('\0'); 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Including a terminating null byte. 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t status_line_len = raw_headers_.size(); 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Now, we add the rest of the raw headers to raw_headers_, and begin parsing 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // it (to populate our parsed_ vector). 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.append(line_end + 1, raw_input.end()); 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Adjust to point at the null byte following the status line 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott line_end = raw_headers_.begin() + status_line_len - 1; 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::HeadersIterator headers(line_end + 1, raw_headers_.end(), 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string(1, '\0')); 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (headers.GetNext()) { 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddHeader(headers.name_begin(), 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.name_end(), 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.values_begin(), 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.values_end()); 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Append all of our headers to the final output string. 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::GetNormalizedHeaders(std::string* output) const { 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // copy up to the null byte. this just copies the status line. 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->assign(raw_headers_.c_str()); 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // headers may appear multiple times (not necessarily in succession) in the 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // header data, so we build a map from header name to generated header lines. 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // to preserve the order of the original headers, the actual values are kept 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // in a separate list. finally, the list of headers is flattened to form 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the normalized block of headers. 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // NOTE: We take special care to preserve the whitespace around any commas 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // that may occur in the original response headers. Because our consumer may 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // be a web app, we cannot be certain of the semantics of commas despite the 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // fact that RFC 2616 says that they should be regarded as value separators. 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott typedef base::hash_map<std::string, size_t> HeadersMap; 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeadersMap headers_map; 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeadersMap::iterator iter = headers_map.end(); 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<std::string> headers; 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < parsed_.size(); ++i) { 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!parsed_[i].is_continuation()); 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string name(parsed_[i].name_begin, parsed_[i].name_end); 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string lower_name = StringToLowerASCII(name); 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott iter = headers_map.find(lower_name); 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (iter == headers_map.end()) { 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott iter = headers_map.insert( 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HeadersMap::value_type(lower_name, headers.size())).first; 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers.push_back(name + ": "); 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers[iter->second].append(", "); 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator value_begin = parsed_[i].value_begin; 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator value_end = parsed_[i].value_end; 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (++i < parsed_.size() && parsed_[i].is_continuation()) 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value_end = parsed_[i].value_end; 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --i; 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott headers[iter->second].append(value_begin, value_end); 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < headers.size(); ++i) { 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->push_back('\n'); 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->append(headers[i]); 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott output->push_back('\n'); 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetNormalizedHeader(const std::string& name, 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* value) const { 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If you hit this assertion, please use EnumerateHeader instead! 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!HttpUtil::IsNonCoalescingHeader(name)); 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value->clear(); 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool found = false; 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t i = 0; 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (i < parsed_.size()) { 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i = FindHeader(i, name); 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == std::string::npos) 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott found = true; 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!value->empty()) 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value->append(", "); 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator value_begin = parsed_[i].value_begin; 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator value_end = parsed_[i].value_end; 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (++i < parsed_.size() && parsed_[i].is_continuation()) 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value_end = parsed_[i].value_end; 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value->append(value_begin, value_end); 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return found; 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string HttpResponseHeaders::GetStatusLine() const { 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // copy up to the null byte. 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::string(raw_headers_.c_str()); 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string HttpResponseHeaders::GetStatusText() const { 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // GetStatusLine() is already normalized, so it has the format: 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // <http_version> SP <response_code> SP <status_text> 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string status_text = GetStatusLine(); 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator begin = status_text.begin(); 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator end = status_text.end(); 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < 2; ++i) 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott begin = find(begin, end, ' ') + 1; 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::string(begin, end); 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::EnumerateHeaderLines(void** iter, 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* name, 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* value) const { 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t i = reinterpret_cast<size_t>(*iter); 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == parsed_.size()) 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!parsed_[i].is_continuation()); 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name->assign(parsed_[i].name_begin, parsed_[i].name_end); 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator value_begin = parsed_[i].value_begin; 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator value_end = parsed_[i].value_end; 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (++i < parsed_.size() && parsed_[i].is_continuation()) 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value_end = parsed_[i].value_end; 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value->assign(value_begin, value_end); 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *iter = reinterpret_cast<void*>(i); 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::EnumerateHeader(void** iter, const std::string& name, 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* value) const { 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t i; 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!iter || !*iter) { 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i = FindHeader(0, name); 491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i = reinterpret_cast<size_t>(*iter); 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i >= parsed_.size()) { 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i = std::string::npos; 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (!parsed_[i].is_continuation()) { 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i = FindHeader(i, name); 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == std::string::npos) { 501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value->clear(); 502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (iter) 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *iter = reinterpret_cast<void*>(i + 1); 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value->assign(parsed_[i].value_begin, parsed_[i].value_end); 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::HasHeaderValue(const std::string& name, 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& value) const { 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The value has to be an exact match. This is important since 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 'cache-control: no-cache' != 'cache-control: no-cache="foo"' 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* iter = NULL; 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string temp; 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (EnumerateHeader(&iter, name, &temp)) { 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (value.size() == temp.size() && 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::equal(temp.begin(), temp.end(), value.begin(), 520513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::CaseInsensitiveCompare<char>())) 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpResponseHeaders::HasHeader(const std::string& name) const { 527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return FindHeader(0, name) != std::string::npos; 528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 53072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenHttpResponseHeaders::HttpResponseHeaders() : response_code_(-1) { 5313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5333345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickHttpResponseHeaders::~HttpResponseHeaders() { 5343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note: this implementation implicitly assumes that line_end points at a valid 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// sentinel character (such as '\0'). 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHttpVersion HttpResponseHeaders::ParseVersion( 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator line_begin, 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator line_end) { 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator p = line_begin; 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // RFC2616 sec 3.1: HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO: (1*DIGIT apparently means one or more digits, but we only handle 1). 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO: handle leading zeros, which is allowed by the rfc1616 sec 3.1. 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((line_end - p < 4) || !LowerCaseEqualsASCII(p, p + 4, "http")) { 549731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "missing status line"; 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return HttpVersion(); 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott p += 4; 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (p >= line_end || *p != '/') { 556731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "missing version"; 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return HttpVersion(); 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator dot = find(p, line_end, '.'); 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dot == line_end) { 562731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "malformed version"; 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return HttpVersion(); 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++p; // from / to first digit. 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++dot; // from . to second digit. 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!(*p >= '0' && *p <= '9' && *dot >= '0' && *dot <= '9')) { 570731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "malformed version number"; 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return HttpVersion(); 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint16 major = *p - '0'; 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint16 minor = *dot - '0'; 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return HttpVersion(major, minor); 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note: this implementation implicitly assumes that line_end points at a valid 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// sentinel character (such as '\0'). 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::ParseStatusLine( 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator line_begin, 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator line_end, 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool has_headers) { 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Extract the version number 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_http_version_ = ParseVersion(line_begin, line_end); 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Clamp the version number to one of: {0.9, 1.0, 1.1} 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (parsed_http_version_ == HttpVersion(0, 9) && !has_headers) { 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott http_version_ = HttpVersion(0, 9); 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_ = "HTTP/0.9"; 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (parsed_http_version_ >= HttpVersion(1, 1)) { 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott http_version_ = HttpVersion(1, 1); 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_ = "HTTP/1.1"; 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Treat everything else like HTTP 1.0 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott http_version_ = HttpVersion(1, 0); 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_ = "HTTP/1.0"; 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (parsed_http_version_ != http_version_) { 602731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "assuming HTTP/" << http_version_.major_value() << "." 603731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << http_version_.minor_value(); 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(eroman): this doesn't make sense if ParseVersion failed. 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator p = find(line_begin, line_end, ' '); 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (p == line_end) { 610731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "missing response status; assuming 200 OK"; 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.append(" 200 OK"); 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.push_back('\0'); 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_code_ = 200; 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Skip whitespace. 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*p == ' ') 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++p; 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator code = p; 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*p >= '0' && *p <= '9') 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++p; 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (p == code) { 626731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "missing response status number; assuming 200"; 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.append(" 200 OK"); 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_code_ = 200; 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.push_back(' '); 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.append(code, p); 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.push_back(' '); 634513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringToInt(code, p, &response_code_); 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Skip whitespace. 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*p == ' ') 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++p; 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Trim trailing whitespace. 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (line_end > p && line_end[-1] == ' ') 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --line_end; 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (p == line_end) { 645731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "missing response status text; assuming OK"; 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Not super critical what we put here. Just use "OK" 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // even if it isn't descriptive of response_code_. 648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.append("OK"); 649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.append(p, line_end); 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott raw_headers_.push_back('\0'); 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottsize_t HttpResponseHeaders::FindHeader(size_t from, 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string& search) const { 658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = from; i < parsed_.size(); ++i) { 659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (parsed_[i].is_continuation()) 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string::const_iterator& name_begin = parsed_[i].name_begin; 662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string::const_iterator& name_end = parsed_[i].name_end; 663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (static_cast<size_t>(name_end - name_begin) == search.size() && 664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::equal(name_begin, name_end, search.begin(), 665513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::CaseInsensitiveCompare<char>())) 666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return i; 667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return std::string::npos; 670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::AddHeader(std::string::const_iterator name_begin, 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator name_end, 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator values_begin, 675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator values_end) { 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the header can be coalesced, then we should split it up. 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (values_begin == values_end || 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::IsNonCoalescingHeader(name_begin, name_end)) { 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddToParsed(name_begin, name_end, values_begin, values_end); 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::ValuesIterator it(values_begin, values_end, ','); 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (it.GetNext()) { 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddToParsed(name_begin, name_end, it.value_begin(), it.value_end()); 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // clobber these so that subsequent values are treated as continuations 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name_begin = name_end = raw_headers_.end(); 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::AddToParsed(std::string::const_iterator name_begin, 691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator name_end, 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator value_begin, 693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator value_end) { 694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ParsedHeader header; 695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header.name_begin = name_begin; 696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header.name_end = name_end; 697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header.value_begin = value_begin; 698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott header.value_end = value_end; 699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott parsed_.push_back(header); 700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::AddNonCacheableHeaders(HeaderSet* result) const { 703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Add server specified transients. Any 'cache-control: no-cache="foo,bar"' 704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // headers present in the response specify additional headers that we should 705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // not store in the cache. 706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string kCacheControl = "cache-control"; 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const std::string kPrefix = "no-cache=\""; 708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string value; 709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* iter = NULL; 710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (EnumerateHeader(&iter, kCacheControl, &value)) { 711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (value.size() > kPrefix.size() && 712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value.compare(0, kPrefix.size(), kPrefix) == 0) { 713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // if it doesn't end with a quote, then treat as malformed 714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (value[value.size()-1] != '\"') 715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // trim off leading and trailing bits 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t len = value.size() - kPrefix.size() - 1; 719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TrimString(value.substr(kPrefix.size(), len), HTTP_LWS, &value); 720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t begin_pos = 0; 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (;;) { 723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // find the end of this header name 724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t comma_pos = value.find(',', begin_pos); 725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (comma_pos == std::string::npos) 726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott comma_pos = value.size(); 727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t end = comma_pos; 728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (end > begin_pos && strchr(HTTP_LWS, value[end - 1])) 729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott end--; 730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // assuming the header is not emtpy, lowercase and insert into set 732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (end > begin_pos) { 733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string name = value.substr(begin_pos, end - begin_pos); 734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StringToLowerASCII(&name); 735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->insert(name); 736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // repeat 739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott begin_pos = comma_pos + 1; 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (begin_pos < value.size() && strchr(HTTP_LWS, value[begin_pos])) 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott begin_pos++; 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (begin_pos >= value.size()) 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::AddHopByHopHeaders(HeaderSet* result) { 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < arraysize(kHopByHopResponseHeaders); ++i) 751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->insert(std::string(kHopByHopResponseHeaders[i])); 752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::AddCookieHeaders(HeaderSet* result) { 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < arraysize(kCookieResponseHeaders); ++i) 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->insert(std::string(kCookieResponseHeaders[i])); 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::AddChallengeHeaders(HeaderSet* result) { 760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < arraysize(kChallengeResponseHeaders); ++i) 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->insert(std::string(kChallengeResponseHeaders[i])); 762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::AddHopContentRangeHeaders(HeaderSet* result) { 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->insert("content-range"); 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid HttpResponseHeaders::GetMimeTypeAndCharset(std::string* mime_type, 769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* charset) const { 770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott mime_type->clear(); 771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott charset->clear(); 772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string name = "content-type"; 774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string value; 775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool had_charset = false; 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* iter = NULL; 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (EnumerateHeader(&iter, name, &value)) 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::ParseContentType(value, mime_type, charset, &had_charset); 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetMimeType(std::string* mime_type) const { 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string unused; 785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetMimeTypeAndCharset(mime_type, &unused); 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return !mime_type->empty(); 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetCharset(std::string* charset) const { 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string unused; 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetMimeTypeAndCharset(&unused, charset); 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return !charset->empty(); 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::IsRedirect(std::string* location) const { 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IsRedirectResponseCode(response_code_)) 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If we lack a Location header, then we can't treat this as a redirect. 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We assume that the first non-empty location value is the target URL that 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we want to follow. TODO(darin): Is this consistent with other browsers? 802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t i = std::string::npos; 803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i = FindHeader(++i, "location"); 805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i == std::string::npos) 806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the location value is empty, then it doesn't count. 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (parsed_[i].value_begin == parsed_[i].value_end); 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (location) { 811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Escape any non-ASCII characters to preserve them. The server should 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // only be returning ASCII here, but for compat we need to do this. 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *location = EscapeNonASCII( 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string(parsed_[i].value_begin, parsed_[i].value_end)); 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::IsRedirectResponseCode(int response_code) { 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Users probably want to see 300 (multiple choice) pages, so we don't count 823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // them as redirects that need to be followed. 824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (response_code == 301 || 825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_code == 302 || 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_code == 303 || 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_code == 307); 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// From RFC 2616 section 13.2.4: 831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The calculation to determine if a response has expired is quite simple: 833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// response_is_fresh = (freshness_lifetime > current_age) 835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Of course, there are other factors that can force a response to always be 837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// validated or re-fetched. 838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::RequiresValidation(const Time& request_time, 840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const Time& response_time, 841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const Time& current_time) const { 842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta lifetime = 843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetFreshnessLifetime(response_time); 844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (lifetime == TimeDelta()) 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return lifetime <= GetCurrentAge(request_time, response_time, current_time); 848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// From RFC 2616 section 13.2.4: 851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The max-age directive takes priority over Expires, so if max-age is present 853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// in a response, the calculation is simply: 854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// freshness_lifetime = max_age_value 856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Otherwise, if Expires is present in the response, the calculation is: 858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// freshness_lifetime = expires_value - date_value 860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note that neither of these calculations is vulnerable to clock skew, since 862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// all of the information comes from the origin server. 863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Also, if the response does have a Last-Modified time, the heuristic 865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// expiration value SHOULD be no more than some fraction of the interval since 866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// that time. A typical setting of this fraction might be 10%: 867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// freshness_lifetime = (date_value - last_modified_value) * 0.10 869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTimeDelta HttpResponseHeaders::GetFreshnessLifetime( 871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const Time& response_time) const { 872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check for headers that force a response to never be fresh. For backwards 873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control: 874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // no-cache" even though RFC 2616 does not specify it. 875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (HasHeaderValue("cache-control", "no-cache") || 876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HasHeaderValue("cache-control", "no-store") || 877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HasHeaderValue("pragma", "no-cache") || 878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HasHeaderValue("vary", "*")) // see RFC 2616 section 13.6 879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TimeDelta(); // not fresh 880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the 882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Expires header after checking for max-age in GetFreshnessLifetime. This 883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is important since "Expires: <date in the past>" means not fresh, but 884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // it should not trump a max-age value. 885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta max_age_value; 887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (GetMaxAgeValue(&max_age_value)) 888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return max_age_value; 889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If there is no Date header, then assume that the server response was 891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // generated at the time when we received the response. 892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time date_value; 893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!GetDateValue(&date_value)) 894c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date_value = response_time; 895c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 896c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time expires_value; 897c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (GetExpiresValue(&expires_value)) { 898c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The expires value can be a date in the past! 899c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (expires_value > date_value) 900c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return expires_value - date_value; 901c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 902c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TimeDelta(); // not fresh 903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 904c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 905c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // From RFC 2616 section 13.4: 906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // A response received with a status code of 200, 203, 206, 300, 301 or 410 908c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // MAY be stored by a cache and used in reply to a subsequent request, 909c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // subject to the expiration mechanism, unless a cache-control directive 910c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // prohibits caching. 911c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ... 912c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // A response received with any other status code (e.g. status codes 302 913c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // and 307) MUST NOT be returned in a reply to a subsequent request unless 914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // there are cache-control directives or another header(s) that explicitly 915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // allow it. 916c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 917c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // From RFC 2616 section 14.9.4: 918c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 919c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // When the must-revalidate directive is present in a response received by 920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a cache, that cache MUST NOT use the entry after it becomes stale to 921c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // respond to a subsequent request without first revalidating it with the 922c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // origin server. (I.e., the cache MUST do an end-to-end revalidation every 923c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // time, if, based solely on the origin server's Expires or max-age value, 924c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the cached response is stale.) 925c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 926c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((response_code_ == 200 || response_code_ == 203 || 927c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott response_code_ == 206) && 928c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott !HasHeaderValue("cache-control", "must-revalidate")) { 929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(darin): Implement a smarter heuristic. 930c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time last_modified_value; 931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (GetLastModifiedValue(&last_modified_value)) { 932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The last-modified value can be a date in the past! 933c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (last_modified_value <= date_value) 934c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (date_value - last_modified_value) / 10; 935c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 936c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 938c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // These responses are implicitly fresh (unless otherwise overruled): 939c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response_code_ == 300 || response_code_ == 301 || response_code_ == 410) 940c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TimeDelta::FromMicroseconds(kint64max); 941c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 942c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return TimeDelta(); // not fresh 943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 944c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 945c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// From RFC 2616 section 13.2.3: 946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 947c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Summary of age calculation algorithm, when a cache receives a response: 948c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 949c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// /* 950c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * age_value 951c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * is the value of Age: header received by the cache with 952c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * this response. 953c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * date_value 954c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * is the value of the origin server's Date: header 955c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * request_time 956c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * is the (local) time when the cache made the request 957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * that resulted in this cached response 958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * response_time 959c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * is the (local) time when the cache received the 960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * response 961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * now 962c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// * is the current (local) time 963c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// */ 964c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// apparent_age = max(0, response_time - date_value); 965c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// corrected_received_age = max(apparent_age, age_value); 966c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// response_delay = response_time - request_time; 967c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// corrected_initial_age = corrected_received_age + response_delay; 968c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// resident_time = now - response_time; 969c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// current_age = corrected_initial_age + resident_time; 970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 971c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottTimeDelta HttpResponseHeaders::GetCurrentAge(const Time& request_time, 972c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const Time& response_time, 973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const Time& current_time) const { 974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If there is no Date header, then assume that the server response was 975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // generated at the time when we received the response. 976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time date_value; 977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!GetDateValue(&date_value)) 978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott date_value = response_time; 979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If there is no Age header, then assume age is zero. GetAgeValue does not 981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // modify its out param if the value does not exist. 982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta age_value; 983c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetAgeValue(&age_value); 984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 985c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta apparent_age = std::max(TimeDelta(), response_time - date_value); 986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta corrected_received_age = std::max(apparent_age, age_value); 987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta response_delay = response_time - request_time; 988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta corrected_initial_age = corrected_received_age + response_delay; 989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta resident_time = current_time - response_time; 990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta current_age = corrected_initial_age + resident_time; 991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return current_age; 993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const { 996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string name = "cache-control"; 997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string value; 998c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char kMaxAgePrefix[] = "max-age="; 1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1; 1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* iter = NULL; 1003c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (EnumerateHeader(&iter, name, &value)) { 1004c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (value.size() > kMaxAgePrefixLen) { 1005c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (LowerCaseEqualsASCII(value.begin(), 1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott value.begin() + kMaxAgePrefixLen, 1007c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott kMaxAgePrefix)) { 10083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int64 seconds; 1009513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch base::StringToInt64(value.begin() + kMaxAgePrefixLen, 1010513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch value.end(), 1011513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch &seconds); 10123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *result = TimeDelta::FromSeconds(seconds); 1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1015c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1016c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1017c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1020c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetAgeValue(TimeDelta* result) const { 1022c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string value; 1023c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!EnumerateHeader(NULL, "Age", &value)) 1024c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1025c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int64 seconds; 10273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick base::StringToInt64(value, &seconds); 10283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *result = TimeDelta::FromSeconds(seconds); 1029c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1030c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1032c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetDateValue(Time* result) const { 1033c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GetTimeValuedHeader("Date", result); 1034c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1035c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1036c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetLastModifiedValue(Time* result) const { 1037c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GetTimeValuedHeader("Last-Modified", result); 1038c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1040c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetExpiresValue(Time* result) const { 1041c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return GetTimeValuedHeader("Expires", result); 1042c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1043c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1044c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetTimeValuedHeader(const std::string& name, 1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time* result) const { 1046c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string value; 1047c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!EnumerateHeader(NULL, name, &value)) 1048c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1049c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::wstring value_wide(value.begin(), value.end()); // inflate ascii 1051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return Time::FromString(value_wide.c_str(), result); 1052c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1053c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1054c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::IsKeepAlive() const { 1055c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (http_version_ < HttpVersion(1, 0)) 1056c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1057c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // NOTE: It is perhaps risky to assume that a Proxy-Connection header is 1059c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // meaningful when we don't know that this response was from a proxy, but 1060c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Mozilla also does this, so we'll do the same. 1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string connection_val; 1062c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!EnumerateHeader(NULL, "connection", &connection_val)) 1063c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnumerateHeader(NULL, "proxy-connection", &connection_val); 1064c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1065c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool keep_alive; 1066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1067c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (http_version_ == HttpVersion(1, 0)) { 1068c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // HTTP/1.0 responses default to NOT keep-alive 1069c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_alive = LowerCaseEqualsASCII(connection_val, "keep-alive"); 1070c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1071c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // HTTP/1.1 responses default to keep-alive 1072c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_alive = !LowerCaseEqualsASCII(connection_val, "close"); 1073c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1074c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1075c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return keep_alive; 1076c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1077c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1078c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::HasStrongValidators() const { 1079c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string etag_value; 1080c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EnumerateHeader(NULL, "etag", &etag_value); 1081c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!etag_value.empty()) { 1082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t slash = etag_value.find('/'); 1083c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (slash == std::string::npos || slash == 0) 1084c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1085c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1086c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator i = etag_value.begin(); 1087c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator j = etag_value.begin() + slash; 1088c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::TrimLWS(&i, &j); 1089c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!LowerCaseEqualsASCII(i, j, "w")) 1090c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1091c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1092c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1093c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time last_modified; 1094c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!GetLastModifiedValue(&last_modified)) 1095c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Time date; 1098c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!GetDateValue(&date)) 1099c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ((date - last_modified).InSeconds() >= 60); 1102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// From RFC 2616: 1105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Content-Length = "Content-Length" ":" 1*DIGIT 1106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint64 HttpResponseHeaders::GetContentLength() const { 1107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* iter = NULL; 1108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string content_length_val; 1109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!EnumerateHeader(&iter, "content-length", &content_length_val)) 1110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 1111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (content_length_val.empty()) 1113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 1114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (content_length_val[0] == '+') 1116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 1117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 result; 11193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool ok = base::StringToInt64(content_length_val, &result); 1120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ok || result < 0) 1121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return -1; 1122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 1124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// From RFC 2616 14.16: 1127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// content-range-spec = 1128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// bytes-unit SP byte-range-resp-spec "/" ( instance-length | "*" ) 1129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) | "*" 1130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// instance-length = 1*DIGIT 1131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// bytes-unit = "bytes" 1132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HttpResponseHeaders::GetContentRange(int64* first_byte_position, 1133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64* last_byte_position, 1134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64* instance_length) const { 1135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* iter = NULL; 1136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string content_range_spec; 1137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *first_byte_position = *last_byte_position = *instance_length = -1; 1138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!EnumerateHeader(&iter, "content-range", &content_range_spec)) 1139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the header value is empty, we have an invalid header. 1142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (content_range_spec.empty()) 1143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t space_position = content_range_spec.find(' '); 1146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (space_position == std::string::npos) 1147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Invalid header if it doesn't contain "bytes-unit". 1150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator content_range_spec_begin = 1151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_range_spec.begin(); 1152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator content_range_spec_end = 1153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_range_spec.begin() + space_position; 1154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::TrimLWS(&content_range_spec_begin, &content_range_spec_end); 1155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!LowerCaseEqualsASCII(content_range_spec_begin, 1156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_range_spec_end, 1157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "bytes")) { 1158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t slash_position = content_range_spec.find('/', space_position + 1); 1162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (slash_position == std::string::npos) 1163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Obtain the part behind the space and before slash. 1166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator byte_range_resp_spec_begin = 1167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_range_spec.begin() + space_position + 1; 1168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator byte_range_resp_spec_end = 1169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_range_spec.begin() + slash_position; 1170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::TrimLWS(&byte_range_resp_spec_begin, &byte_range_resp_spec_end); 1171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Parse the byte-range-resp-spec part. 1173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string byte_range_resp_spec(byte_range_resp_spec_begin, 1174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott byte_range_resp_spec_end); 1175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If byte-range-resp-spec != "*". 1176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!LowerCaseEqualsASCII(byte_range_resp_spec, "*")) { 1177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t minus_position = byte_range_resp_spec.find('-'); 1178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (minus_position != std::string::npos) { 1179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Obtain first-byte-pos. 1180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator first_byte_pos_begin = 1181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott byte_range_resp_spec.begin(); 1182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator first_byte_pos_end = 1183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott byte_range_resp_spec.begin() + minus_position; 1184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end); 1185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1186513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch bool ok = base::StringToInt64(first_byte_pos_begin, 1187513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch first_byte_pos_end, 1188513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch first_byte_position); 1189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Obtain last-byte-pos. 1191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator last_byte_pos_begin = 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch byte_range_resp_spec.begin() + minus_position + 1; 1193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator last_byte_pos_end = 1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch byte_range_resp_spec.end(); 1195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::TrimLWS(&last_byte_pos_begin, &last_byte_pos_end); 1196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1197513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch ok &= base::StringToInt64(last_byte_pos_begin, 1198513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch last_byte_pos_end, 1199513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch last_byte_position); 1200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ok) { 1201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *first_byte_position = *last_byte_position = -1; 1202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*first_byte_position < 0 || *last_byte_position < 0 || 1205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *first_byte_position > *last_byte_position) 1206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 1208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Parse the instance-length part. 1213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If instance-length == "*". 1214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator instance_length_begin = 1215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_range_spec.begin() + slash_position + 1; 1216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string::const_iterator instance_length_end = 1217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott content_range_spec.end(); 1218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HttpUtil::TrimLWS(&instance_length_begin, &instance_length_end); 1219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (LowerCaseEqualsASCII(instance_length_begin, instance_length_end, "*")) { 1221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1222513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } else if (!base::StringToInt64(instance_length_begin, 1223513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch instance_length_end, 1224513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch instance_length)) { 1225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *instance_length = -1; 1226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 1228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We have all the values; let's verify that they make sense for a 206 1230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // response. 1231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (*first_byte_position < 0 || *last_byte_position < 0 || 1232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *instance_length < 0 || *instance_length - 1 < *last_byte_position) 1233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 1234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 1236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 1237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 1238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 1239