// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// HttpRequestHeaders manages the request headers.
// It maintains these in a vector of header key/value pairs, thereby maintaining
// the order of the headers. This means that any lookups are linear time
// operations.
#ifndef NET_HTTP_HTTP_REQUEST_HEADERS_H_
#define NET_HTTP_HTTP_REQUEST_HEADERS_H_
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/base/net_log.h"
namespace net {
class NET_EXPORT HttpRequestHeaders {
public:
struct HeaderKeyValuePair {
HeaderKeyValuePair();
HeaderKeyValuePair(const base::StringPiece& key,
const base::StringPiece& value);
std::string key;
std::string value;
};
typedef std::vector<HeaderKeyValuePair> HeaderVector;
class NET_EXPORT Iterator {
public:
explicit Iterator(const HttpRequestHeaders& headers);
~Iterator();
// Advances the iterator to the next header, if any. Returns true if there
// is a next header. Use name() and value() methods to access the resultant
// header name and value.
bool GetNext();
// These two accessors are only valid if GetNext() returned true.
const std::string& name() const { return curr_->key; }
const std::string& value() const { return curr_->value; }
private:
bool started_;
HttpRequestHeaders::HeaderVector::const_iterator curr_;
const HttpRequestHeaders::HeaderVector::const_iterator end_;
DISALLOW_COPY_AND_ASSIGN(Iterator);
};
static const char kGetMethod[];
static const char kAcceptCharset[];
static const char kAcceptEncoding[];
static const char kAcceptLanguage[];
static const char kAuthorization[];
static const char kCacheControl[];
static const char kConnection[];
static const char kContentType[];
static const char kCookie[];
static const char kContentLength[];
static const char kHost[];
static const char kIfModifiedSince[];
static const char kIfNoneMatch[];
static const char kIfRange[];
static const char kOrigin[];
static const char kPragma[];
static const char kProxyAuthorization[];
static const char kProxyConnection[];
static const char kRange[];
static const char kReferer[];
static const char kUserAgent[];
static const char kTransferEncoding[];
HttpRequestHeaders();
~HttpRequestHeaders();
bool IsEmpty() const { return headers_.empty(); }
bool HasHeader(const base::StringPiece& key) const {
return FindHeader(key) != headers_.end();
}
// Gets the first header that matches |key|. If found, returns true and
// writes the value to |out|.
bool GetHeader(const base::StringPiece& key, std::string* out) const;
// Clears all the headers.
void Clear();
// Sets the header value pair for |key| and |value|. If |key| already exists,
// then the header value is modified, but the key is untouched, and the order
// in the vector remains the same. When comparing |key|, case is ignored.
void SetHeader(const base::StringPiece& key, const base::StringPiece& value);
// Sets the header value pair for |key| and |value|, if |key| does not exist.
// If |key| already exists, the call is a no-op.
// When comparing |key|, case is ignored.
void SetHeaderIfMissing(const base::StringPiece& key,
const base::StringPiece& value);
// Removes the first header that matches (case insensitive) |key|.
void RemoveHeader(const base::StringPiece& key);
// Parses the header from a string and calls SetHeader() with it. This string
// should not contain any CRLF. As per RFC2616, the format is:
//
// message-header = field-name ":" [ field-value ]
// field-name = token
// field-value = *( field-content | LWS )
// field-content = <the OCTETs making up the field-value
// and consisting of either *TEXT or combinations
// of token, separators, and quoted-string>
//
// AddHeaderFromString() will trim any LWS surrounding the
// field-content.
void AddHeaderFromString(const base::StringPiece& header_line);
// Same thing as AddHeaderFromString() except that |headers| is a "\r\n"
// delimited string of header lines. It will split up the string by "\r\n"
// and call AddHeaderFromString() on each.
void AddHeadersFromString(const base::StringPiece& headers);
// Calls SetHeader() on each header from |other|, maintaining order.
void MergeFrom(const HttpRequestHeaders& other);
// Copies from |other| to |this|.
void CopyFrom(const HttpRequestHeaders& other) {
*this = other;
}
void Swap(HttpRequestHeaders* other) {
headers_.swap(other->headers_);
}
// Serializes HttpRequestHeaders to a string representation. Joins all the
// header keys and values with ": ", and inserts "\r\n" between each header
// line, and adds the trailing "\r\n".
std::string ToString() const;
// Takes in the request line and returns a Value for use with the NetLog
// containing both the request line and all headers fields.
base::Value* NetLogCallback(const std::string* request_line,
NetLog::LogLevel log_level) const;
// Takes in a Value created by the above function, and attempts to extract the
// request line and create a copy of the original headers. Returns true on
// success. On failure, clears |headers| and |request_line|.
// TODO(mmenke): Long term, we want to remove this, and migrate external
// consumers to be NetworkDelegates.
static bool FromNetLogParam(const base::Value* event_param,
HttpRequestHeaders* headers,
std::string* request_line);
private:
HeaderVector::iterator FindHeader(const base::StringPiece& key);
HeaderVector::const_iterator FindHeader(const base::StringPiece& key) const;
HeaderVector headers_;
// Allow the copy construction and operator= to facilitate copying in
// HttpRequestHeaders.
// TODO(willchan): Investigate to see if we can remove the need to copy
// HttpRequestHeaders.
// DISALLOW_COPY_AND_ASSIGN(HttpRequestHeaders);
};
} // namespace net
#endif // NET_HTTP_HTTP_REQUEST_HEADERS_H_