| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef NET_HTTP_HTTP_RESPONSE_HEADERS_H_ | |
| 6 #define NET_HTTP_HTTP_RESPONSE_HEADERS_H_ | |
| 7 | |
| 8 #include <string> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/basictypes.h" | |
| 12 #include "base/containers/hash_tables.h" | |
| 13 #include "base/memory/ref_counted.h" | |
| 14 #include "base/strings/string_piece.h" | |
| 15 #include "net/base/net_export.h" | |
| 16 #include "net/base/net_log.h" | |
| 17 #include "net/http/http_version.h" | |
| 18 | |
| 19 class Pickle; | |
| 20 class PickleIterator; | |
| 21 | |
| 22 namespace base { | |
| 23 class Time; | |
| 24 class TimeDelta; | |
| 25 } | |
| 26 | |
| 27 namespace net { | |
| 28 | |
| 29 class HttpByteRange; | |
| 30 | |
| 31 enum ValidationType { | |
| 32 VALIDATION_NONE, // The resource is fresh. | |
| 33 VALIDATION_ASYNCHRONOUS, // The resource requires async revalidation. | |
| 34 VALIDATION_SYNCHRONOUS // The resource requires sync revalidation. | |
| 35 }; | |
| 36 | |
| 37 // HttpResponseHeaders: parses and holds HTTP response headers. | |
| 38 class NET_EXPORT HttpResponseHeaders | |
| 39 : public base::RefCountedThreadSafe<HttpResponseHeaders> { | |
| 40 public: | |
| 41 // Persist options. | |
| 42 typedef int PersistOptions; | |
| 43 static const PersistOptions PERSIST_RAW = -1; // Raw, unparsed headers. | |
| 44 static const PersistOptions PERSIST_ALL = 0; // Parsed headers. | |
| 45 static const PersistOptions PERSIST_SANS_COOKIES = 1 << 0; | |
| 46 static const PersistOptions PERSIST_SANS_CHALLENGES = 1 << 1; | |
| 47 static const PersistOptions PERSIST_SANS_HOP_BY_HOP = 1 << 2; | |
| 48 static const PersistOptions PERSIST_SANS_NON_CACHEABLE = 1 << 3; | |
| 49 static const PersistOptions PERSIST_SANS_RANGES = 1 << 4; | |
| 50 static const PersistOptions PERSIST_SANS_SECURITY_STATE = 1 << 5; | |
| 51 | |
| 52 struct FreshnessLifetimes { | |
| 53 // How long the resource will be fresh for. | |
| 54 base::TimeDelta freshness; | |
| 55 // How long after becoming not fresh that the resource will be stale but | |
| 56 // usable (if async revalidation is enabled). | |
| 57 base::TimeDelta staleness; | |
| 58 }; | |
| 59 | |
| 60 static const char kContentRange[]; | |
| 61 | |
| 62 // Parses the given raw_headers. raw_headers should be formatted thus: | |
| 63 // includes the http status response line, each line is \0-terminated, and | |
| 64 // it's terminated by an empty line (ie, 2 \0s in a row). | |
| 65 // (Note that line continuations should have already been joined; | |
| 66 // see HttpUtil::AssembleRawHeaders) | |
| 67 // | |
| 68 // HttpResponseHeaders does not perform any encoding changes on the input. | |
| 69 // | |
| 70 explicit HttpResponseHeaders(const std::string& raw_headers); | |
| 71 | |
| 72 // Initializes from the representation stored in the given pickle. The data | |
| 73 // for this object is found relative to the given pickle_iter, which should | |
| 74 // be passed to the pickle's various Read* methods. | |
| 75 explicit HttpResponseHeaders(PickleIterator* pickle_iter); | |
| 76 | |
| 77 // Appends a representation of this object to the given pickle. | |
| 78 // The options argument can be a combination of PersistOptions. | |
| 79 void Persist(Pickle* pickle, PersistOptions options); | |
| 80 | |
| 81 // Performs header merging as described in 13.5.3 of RFC 2616. | |
| 82 void Update(const HttpResponseHeaders& new_headers); | |
| 83 | |
| 84 // Removes all instances of a particular header. | |
| 85 void RemoveHeader(const std::string& name); | |
| 86 | |
| 87 // Removes a particular header line. The header name is compared | |
| 88 // case-insensitively. | |
| 89 void RemoveHeaderLine(const std::string& name, const std::string& value); | |
| 90 | |
| 91 // Adds a particular header. |header| has to be a single header without any | |
| 92 // EOL termination, just [<header-name>: <header-values>] | |
| 93 // If a header with the same name is already stored, the two headers are not | |
| 94 // merged together by this method; the one provided is simply put at the | |
| 95 // end of the list. | |
| 96 void AddHeader(const std::string& header); | |
| 97 | |
| 98 // Replaces the current status line with the provided one (|new_status| should | |
| 99 // not have any EOL). | |
| 100 void ReplaceStatusLine(const std::string& new_status); | |
| 101 | |
| 102 // Updates headers (Content-Length and Content-Range) in the |headers| to | |
| 103 // include the right content length and range for |byte_range|. This also | |
| 104 // updates HTTP status line if |replace_status_line| is true. | |
| 105 // |byte_range| must have a valid, bounded range (i.e. coming from a valid | |
| 106 // response or should be usable for a response). | |
| 107 void UpdateWithNewRange(const HttpByteRange& byte_range, | |
| 108 int64 resource_size, | |
| 109 bool replace_status_line); | |
| 110 | |
| 111 // Creates a normalized header string. The output will be formatted exactly | |
| 112 // like so: | |
| 113 // HTTP/<version> <status_code> <status_text>\n | |
| 114 // [<header-name>: <header-values>\n]* | |
| 115 // meaning, each line is \n-terminated, and there is no extra whitespace | |
| 116 // beyond the single space separators shown (of course, values can contain | |
| 117 // whitespace within them). If a given header-name appears more than once | |
| 118 // in the set of headers, they are combined into a single line like so: | |
| 119 // <header-name>: <header-value1>, <header-value2>, ...<header-valueN>\n | |
| 120 // | |
| 121 // DANGER: For some headers (e.g., "Set-Cookie"), the normalized form can be | |
| 122 // a lossy format. This is due to the fact that some servers generate | |
| 123 // Set-Cookie headers that contain unquoted commas (usually as part of the | |
| 124 // value of an "expires" attribute). So, use this function with caution. Do | |
| 125 // not expect to be able to re-parse Set-Cookie headers from this output. | |
| 126 // | |
| 127 // NOTE: Do not make any assumptions about the encoding of this output | |
| 128 // string. It may be non-ASCII, and the encoding used by the server is not | |
| 129 // necessarily known to us. Do not assume that this output is UTF-8! | |
| 130 // | |
| 131 // TODO(darin): remove this method | |
| 132 // | |
| 133 void GetNormalizedHeaders(std::string* output) const; | |
| 134 | |
| 135 // Fetch the "normalized" value of a single header, where all values for the | |
| 136 // header name are separated by commas. See the GetNormalizedHeaders for | |
| 137 // format details. Returns false if this header wasn't found. | |
| 138 // | |
| 139 // NOTE: Do not make any assumptions about the encoding of this output | |
| 140 // string. It may be non-ASCII, and the encoding used by the server is not | |
| 141 // necessarily known to us. Do not assume that this output is UTF-8! | |
| 142 // | |
| 143 // TODO(darin): remove this method | |
| 144 // | |
| 145 bool GetNormalizedHeader(const std::string& name, std::string* value) const; | |
| 146 | |
| 147 // Returns the normalized status line. For HTTP/0.9 responses (i.e., | |
| 148 // responses that lack a status line), this is the manufactured string | |
| 149 // "HTTP/0.9 200 OK". | |
| 150 std::string GetStatusLine() const; | |
| 151 | |
| 152 // Get the HTTP version of the normalized status line. | |
| 153 HttpVersion GetHttpVersion() const { | |
| 154 return http_version_; | |
| 155 } | |
| 156 | |
| 157 // Get the HTTP version determined while parsing; or (0,0) if parsing failed | |
| 158 HttpVersion GetParsedHttpVersion() const { | |
| 159 return parsed_http_version_; | |
| 160 } | |
| 161 | |
| 162 // Get the HTTP status text of the normalized status line. | |
| 163 std::string GetStatusText() const; | |
| 164 | |
| 165 // Enumerate the "lines" of the response headers. This skips over the status | |
| 166 // line. Use GetStatusLine if you are interested in that. Note that this | |
| 167 // method returns the un-coalesced response header lines, so if a response | |
| 168 // header appears on multiple lines, then it will appear multiple times in | |
| 169 // this enumeration (in the order the header lines were received from the | |
| 170 // server). Also, a given header might have an empty value. Initialize a | |
| 171 // 'void*' variable to NULL and pass it by address to EnumerateHeaderLines. | |
| 172 // Call EnumerateHeaderLines repeatedly until it returns false. The | |
| 173 // out-params 'name' and 'value' are set upon success. | |
| 174 bool EnumerateHeaderLines(void** iter, | |
| 175 std::string* name, | |
| 176 std::string* value) const; | |
| 177 | |
| 178 // Enumerate the values of the specified header. If you are only interested | |
| 179 // in the first header, then you can pass NULL for the 'iter' parameter. | |
| 180 // Otherwise, to iterate across all values for the specified header, | |
| 181 // initialize a 'void*' variable to NULL and pass it by address to | |
| 182 // EnumerateHeader. Note that a header might have an empty value. Call | |
| 183 // EnumerateHeader repeatedly until it returns false. | |
| 184 bool EnumerateHeader(void** iter, | |
| 185 const base::StringPiece& name, | |
| 186 std::string* value) const; | |
| 187 | |
| 188 // Returns true if the response contains the specified header-value pair. | |
| 189 // Both name and value are compared case insensitively. | |
| 190 bool HasHeaderValue(const base::StringPiece& name, | |
| 191 const base::StringPiece& value) const; | |
| 192 | |
| 193 // Returns true if the response contains the specified header. | |
| 194 // The name is compared case insensitively. | |
| 195 bool HasHeader(const base::StringPiece& name) const; | |
| 196 | |
| 197 // Get the mime type and charset values in lower case form from the headers. | |
| 198 // Empty strings are returned if the values are not present. | |
| 199 void GetMimeTypeAndCharset(std::string* mime_type, | |
| 200 std::string* charset) const; | |
| 201 | |
| 202 // Get the mime type in lower case from the headers. If there's no mime | |
| 203 // type, returns false. | |
| 204 bool GetMimeType(std::string* mime_type) const; | |
| 205 | |
| 206 // Get the charset in lower case from the headers. If there's no charset, | |
| 207 // returns false. | |
| 208 bool GetCharset(std::string* charset) const; | |
| 209 | |
| 210 // Returns true if this response corresponds to a redirect. The target | |
| 211 // location of the redirect is optionally returned if location is non-null. | |
| 212 bool IsRedirect(std::string* location) const; | |
| 213 | |
| 214 // Returns true if the HTTP response code passed in corresponds to a | |
| 215 // redirect. | |
| 216 static bool IsRedirectResponseCode(int response_code); | |
| 217 | |
| 218 // Returns VALIDATION_NONE if the response can be reused without | |
| 219 // validation. VALIDATION_ASYNCHRONOUS means the response can be re-used, but | |
| 220 // asynchronous revalidation must be performed. VALIDATION_SYNCHRONOUS means | |
| 221 // that the result cannot be reused without revalidation. | |
| 222 // The result is relative to the current_time parameter, which is | |
| 223 // a parameter to support unit testing. The request_time parameter indicates | |
| 224 // the time at which the request was made that resulted in this response, | |
| 225 // which was received at response_time. | |
| 226 ValidationType RequiresValidation(const base::Time& request_time, | |
| 227 const base::Time& response_time, | |
| 228 const base::Time& current_time) const; | |
| 229 | |
| 230 // Calculates the amount of time the server claims the response is fresh from | |
| 231 // the time the response was generated. See section 13.2.4 of RFC 2616. See | |
| 232 // RequiresValidation for a description of the response_time parameter. See | |
| 233 // the definition of FreshnessLifetimes above for the meaning of the return | |
| 234 // value. See RFC 5861 section 3 for the definition of | |
| 235 // stale-while-revalidate. | |
| 236 FreshnessLifetimes GetFreshnessLifetimes( | |
| 237 const base::Time& response_time) const; | |
| 238 | |
| 239 // Returns the age of the response. See section 13.2.3 of RFC 2616. | |
| 240 // See RequiresValidation for a description of this method's parameters. | |
| 241 base::TimeDelta GetCurrentAge(const base::Time& request_time, | |
| 242 const base::Time& response_time, | |
| 243 const base::Time& current_time) const; | |
| 244 | |
| 245 // The following methods extract values from the response headers. If a | |
| 246 // value is not present, then false is returned. Otherwise, true is returned | |
| 247 // and the out param is assigned to the corresponding value. | |
| 248 bool GetMaxAgeValue(base::TimeDelta* value) const; | |
| 249 bool GetAgeValue(base::TimeDelta* value) const; | |
| 250 bool GetDateValue(base::Time* value) const; | |
| 251 bool GetLastModifiedValue(base::Time* value) const; | |
| 252 bool GetExpiresValue(base::Time* value) const; | |
| 253 bool GetStaleWhileRevalidateValue(base::TimeDelta* value) const; | |
| 254 | |
| 255 // Extracts the time value of a particular header. This method looks for the | |
| 256 // first matching header value and parses its value as a HTTP-date. | |
| 257 bool GetTimeValuedHeader(const std::string& name, base::Time* result) const; | |
| 258 | |
| 259 // Determines if this response indicates a keep-alive connection. | |
| 260 bool IsKeepAlive() const; | |
| 261 | |
| 262 // Returns true if this response has a strong etag or last-modified header. | |
| 263 // See section 13.3.3 of RFC 2616. | |
| 264 bool HasStrongValidators() const; | |
| 265 | |
| 266 // Extracts the value of the Content-Length header or returns -1 if there is | |
| 267 // no such header in the response. | |
| 268 int64 GetContentLength() const; | |
| 269 | |
| 270 // Extracts the value of the specified header or returns -1 if there is no | |
| 271 // such header in the response. | |
| 272 int64 GetInt64HeaderValue(const std::string& header) const; | |
| 273 | |
| 274 // Extracts the values in a Content-Range header and returns true if they are | |
| 275 // valid for a 206 response; otherwise returns false. | |
| 276 // The following values will be outputted: | |
| 277 // |*first_byte_position| = inclusive position of the first byte of the range | |
| 278 // |*last_byte_position| = inclusive position of the last byte of the range | |
| 279 // |*instance_length| = size in bytes of the object requested | |
| 280 // If any of the above values is unknown, its value will be -1. | |
| 281 bool GetContentRange(int64* first_byte_position, | |
| 282 int64* last_byte_position, | |
| 283 int64* instance_length) const; | |
| 284 | |
| 285 // Returns true if the response is chunk-encoded. | |
| 286 bool IsChunkEncoded() const; | |
| 287 | |
| 288 // Creates a Value for use with the NetLog containing the response headers. | |
| 289 base::Value* NetLogCallback(NetLog::LogLevel log_level) const; | |
| 290 | |
| 291 // Takes in a Value created by the above function, and attempts to create a | |
| 292 // copy of the original headers. Returns true on success. On failure, | |
| 293 // clears |http_response_headers|. | |
| 294 // TODO(mmenke): Long term, we want to remove this, and migrate external | |
| 295 // consumers to be NetworkDelegates. | |
| 296 static bool FromNetLogParam( | |
| 297 const base::Value* event_param, | |
| 298 scoped_refptr<HttpResponseHeaders>* http_response_headers); | |
| 299 | |
| 300 // Returns the HTTP response code. This is 0 if the response code text seems | |
| 301 // to exist but could not be parsed. Otherwise, it defaults to 200 if the | |
| 302 // response code is not found in the raw headers. | |
| 303 int response_code() const { return response_code_; } | |
| 304 | |
| 305 // Returns the raw header string. | |
| 306 const std::string& raw_headers() const { return raw_headers_; } | |
| 307 | |
| 308 private: | |
| 309 friend class base::RefCountedThreadSafe<HttpResponseHeaders>; | |
| 310 | |
| 311 typedef base::hash_set<std::string> HeaderSet; | |
| 312 | |
| 313 // The members of this structure point into raw_headers_. | |
| 314 struct ParsedHeader; | |
| 315 typedef std::vector<ParsedHeader> HeaderList; | |
| 316 | |
| 317 HttpResponseHeaders(); | |
| 318 ~HttpResponseHeaders(); | |
| 319 | |
| 320 // Initializes from the given raw headers. | |
| 321 void Parse(const std::string& raw_input); | |
| 322 | |
| 323 // Helper function for ParseStatusLine. | |
| 324 // Tries to extract the "HTTP/X.Y" from a status line formatted like: | |
| 325 // HTTP/1.1 200 OK | |
| 326 // with line_begin and end pointing at the begin and end of this line. If the | |
| 327 // status line is malformed, returns HttpVersion(0,0). | |
| 328 static HttpVersion ParseVersion(std::string::const_iterator line_begin, | |
| 329 std::string::const_iterator line_end); | |
| 330 | |
| 331 // Tries to extract the status line from a header block, given the first | |
| 332 // line of said header block. If the status line is malformed, we'll | |
| 333 // construct a valid one. Example input: | |
| 334 // HTTP/1.1 200 OK | |
| 335 // with line_begin and end pointing at the begin and end of this line. | |
| 336 // Output will be a normalized version of this. | |
| 337 void ParseStatusLine(std::string::const_iterator line_begin, | |
| 338 std::string::const_iterator line_end, | |
| 339 bool has_headers); | |
| 340 | |
| 341 // Find the header in our list (case-insensitive) starting with parsed_ at | |
| 342 // index |from|. Returns string::npos if not found. | |
| 343 size_t FindHeader(size_t from, const base::StringPiece& name) const; | |
| 344 | |
| 345 // Search the Cache-Control header for a directive matching |directive|. If | |
| 346 // present, treat its value as a time offset in seconds, write it to |result|, | |
| 347 // and return true. | |
| 348 bool GetCacheControlDirective(const base::StringPiece& directive, | |
| 349 base::TimeDelta* result) const; | |
| 350 | |
| 351 // Add a header->value pair to our list. If we already have header in our | |
| 352 // list, append the value to it. | |
| 353 void AddHeader(std::string::const_iterator name_begin, | |
| 354 std::string::const_iterator name_end, | |
| 355 std::string::const_iterator value_begin, | |
| 356 std::string::const_iterator value_end); | |
| 357 | |
| 358 // Add to parsed_ given the fields of a ParsedHeader object. | |
| 359 void AddToParsed(std::string::const_iterator name_begin, | |
| 360 std::string::const_iterator name_end, | |
| 361 std::string::const_iterator value_begin, | |
| 362 std::string::const_iterator value_end); | |
| 363 | |
| 364 // Replaces the current headers with the merged version of |raw_headers| and | |
| 365 // the current headers without the headers in |headers_to_remove|. Note that | |
| 366 // |headers_to_remove| are removed from the current headers (before the | |
| 367 // merge), not after the merge. | |
| 368 void MergeWithHeaders(const std::string& raw_headers, | |
| 369 const HeaderSet& headers_to_remove); | |
| 370 | |
| 371 // Adds the values from any 'cache-control: no-cache="foo,bar"' headers. | |
| 372 void AddNonCacheableHeaders(HeaderSet* header_names) const; | |
| 373 | |
| 374 // Adds the set of header names that contain cookie values. | |
| 375 static void AddSensitiveHeaders(HeaderSet* header_names); | |
| 376 | |
| 377 // Adds the set of rfc2616 hop-by-hop response headers. | |
| 378 static void AddHopByHopHeaders(HeaderSet* header_names); | |
| 379 | |
| 380 // Adds the set of challenge response headers. | |
| 381 static void AddChallengeHeaders(HeaderSet* header_names); | |
| 382 | |
| 383 // Adds the set of cookie response headers. | |
| 384 static void AddCookieHeaders(HeaderSet* header_names); | |
| 385 | |
| 386 // Adds the set of content range response headers. | |
| 387 static void AddHopContentRangeHeaders(HeaderSet* header_names); | |
| 388 | |
| 389 // Adds the set of transport security state headers. | |
| 390 static void AddSecurityStateHeaders(HeaderSet* header_names); | |
| 391 | |
| 392 // We keep a list of ParsedHeader objects. These tell us where to locate the | |
| 393 // header-value pairs within raw_headers_. | |
| 394 HeaderList parsed_; | |
| 395 | |
| 396 // The raw_headers_ consists of the normalized status line (terminated with a | |
| 397 // null byte) and then followed by the raw null-terminated headers from the | |
| 398 // input that was passed to our constructor. We preserve the input [*] to | |
| 399 // maintain as much ancillary fidelity as possible (since it is sometimes | |
| 400 // hard to tell what may matter down-stream to a consumer of XMLHttpRequest). | |
| 401 // [*] The status line may be modified. | |
| 402 std::string raw_headers_; | |
| 403 | |
| 404 // This is the parsed HTTP response code. | |
| 405 int response_code_; | |
| 406 | |
| 407 // The normalized http version (consistent with what GetStatusLine() returns). | |
| 408 HttpVersion http_version_; | |
| 409 | |
| 410 // The parsed http version number (not normalized). | |
| 411 HttpVersion parsed_http_version_; | |
| 412 | |
| 413 DISALLOW_COPY_AND_ASSIGN(HttpResponseHeaders); | |
| 414 }; | |
| 415 | |
| 416 } // namespace net | |
| 417 | |
| 418 #endif // NET_HTTP_HTTP_RESPONSE_HEADERS_H_ | |
| OLD | NEW |