blob: b86a379596a600207c6c853d31a7bd2c42b41493 [file] [log] [blame]
// Copyright 2012 The Chromium Authors
// 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 <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
#include "base/containers/flat_set.h"
#include "base/values.h"
#include "net/base/net_export.h"
#include "net/filter/source_stream_type.h"
#include "net/log/net_log_capture_mode.h"
#include "url/gurl.h"
namespace net {
class NET_EXPORT HttpRequestHeaders {
public:
struct NET_EXPORT HeaderKeyValuePair {
HeaderKeyValuePair();
HeaderKeyValuePair(std::string_view key, std::string_view value);
HeaderKeyValuePair(std::string_view key, std::string&& value);
// Inline to take advantage of the std::string_view constructor being
// constexpr.
HeaderKeyValuePair(std::string_view key, const char* value)
: HeaderKeyValuePair(key, std::string_view(value)) {}
bool operator==(const HeaderKeyValuePair& other) const = default;
std::string key;
std::string value;
};
typedef std::vector<HeaderKeyValuePair> HeaderVector;
class NET_EXPORT Iterator {
public:
explicit Iterator(const HttpRequestHeaders& headers);
Iterator(const Iterator&) = delete;
Iterator& operator=(const Iterator&) = delete;
~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_ = false;
HttpRequestHeaders::HeaderVector::const_iterator curr_;
const HttpRequestHeaders::HeaderVector::const_iterator end_;
};
static constexpr char kConnectMethod[] = "CONNECT";
static constexpr char kDeleteMethod[] = "DELETE";
static constexpr char kGetMethod[] = "GET";
static constexpr char kHeadMethod[] = "HEAD";
static constexpr char kOptionsMethod[] = "OPTIONS";
static constexpr char kPatchMethod[] = "PATCH";
static constexpr char kPostMethod[] = "POST";
static constexpr char kPutMethod[] = "PUT";
static constexpr char kTraceMethod[] = "TRACE";
static constexpr char kTrackMethod[] = "TRACK";
static constexpr char kAccept[] = "Accept";
static constexpr char kAcceptCharset[] = "Accept-Charset";
static constexpr char kAcceptEncoding[] = "Accept-Encoding";
static constexpr char kAcceptLanguage[] = "Accept-Language";
static constexpr char kAuthorization[] = "Authorization";
static constexpr char kCacheControl[] = "Cache-Control";
static constexpr char kConnection[] = "Connection";
static constexpr char kContentLength[] = "Content-Length";
static constexpr char kContentType[] = "Content-Type";
static constexpr char kCookie[] = "Cookie";
static constexpr char kHost[] = "Host";
static constexpr char kIfMatch[] = "If-Match";
static constexpr char kIfModifiedSince[] = "If-Modified-Since";
static constexpr char kIfNoneMatch[] = "If-None-Match";
static constexpr char kIfRange[] = "If-Range";
static constexpr char kIfUnmodifiedSince[] = "If-Unmodified-Since";
static constexpr char kOrigin[] = "Origin";
static constexpr char kPragma[] = "Pragma";
static constexpr char kPriority[] = "Priority";
static constexpr char kProxyAuthorization[] = "Proxy-Authorization";
static constexpr char kProxyConnection[] = "Proxy-Connection";
static constexpr char kRange[] = "Range";
static constexpr char kReferer[] = "Referer";
static constexpr char kTransferEncoding[] = "Transfer-Encoding";
static constexpr char kUserAgent[] = "User-Agent";
HttpRequestHeaders();
HttpRequestHeaders(const HttpRequestHeaders& other);
HttpRequestHeaders(HttpRequestHeaders&& other);
~HttpRequestHeaders();
HttpRequestHeaders& operator=(const HttpRequestHeaders& other);
HttpRequestHeaders& operator=(HttpRequestHeaders&& other);
bool IsEmpty() const { return headers_.empty(); }
bool HasHeader(std::string_view key) const {
return FindHeader(key) != headers_.end();
}
// Gets the first header that matches `key`, if one exists. If none exist,
// returns std::nullopt.
std::optional<std::string_view> GetHeaderView(std::string_view key) const;
std::optional<std::string> GetHeader(std::string_view key) 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.
// The caller must ensure that |key| passes HttpUtil::IsValidHeaderName() and
// |value| passes HttpUtil::IsValidHeaderValue().
void SetHeader(std::string_view key, std::string_view value);
void SetHeader(std::string_view key, std::string&& value);
// Inline to take advantage of the std::string_view constructor being
// constexpr.
void SetHeader(std::string_view key, const char* value) {
SetHeader(key, std::string_view(value));
}
// Does the same as above but without internal DCHECKs for validations.
void SetHeaderWithoutCheckForTesting(std::string_view key,
std::string_view 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.
//
// The caller must ensure that |key| passes HttpUtil::IsValidHeaderName() and
// |value| passes HttpUtil::IsValidHeaderValue().
void SetHeaderIfMissing(std::string_view key, std::string_view value);
// Removes the first header that matches (case insensitive) |key|.
void RemoveHeader(std::string_view key);
// Parses the header from a string and calls SetHeader() with it. This string
// should not contain any CRLF. As per RFC7230 Section 3.2, the format is:
//
// header-field = field-name ":" OWS field-value OWS
//
// field-name = token
// field-value = *( field-content / obs-fold )
// field-content = field-vchar [ 1*( SP / HTAB ) field-vchar ]
// field-vchar = VCHAR / obs-text
//
// obs-fold = CRLF 1*( SP / HTAB )
// ; obsolete line folding
// ; see Section 3.2.4
//
// AddHeaderFromString() will trim any LWS surrounding the
// field-content.
void AddHeaderFromString(std::string_view 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(std::string_view headers);
// Calls SetHeader() on each header from |other|, maintaining order.
void MergeFrom(const HttpRequestHeaders& 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::Dict NetLogParams(const std::string& request_line,
NetLogCaptureMode capture_mode) const;
const HeaderVector& GetHeaderVector() const { return headers_; }
// Sets Accept-Encoding header based on `url` and `accepted_stream_types`, if
// it does not exist. "br" is appended only when `enable_brotli` is true.
void SetAcceptEncodingIfMissing(
const GURL& url,
const std::optional<base::flat_set<SourceStreamType>>&
accepted_stream_types,
bool enable_brotli,
bool enable_zstd);
private:
HeaderVector::iterator FindHeader(std::string_view key);
HeaderVector::const_iterator FindHeader(std::string_view key) const;
void SetHeaderInternal(std::string_view key, std::string&& value);
HeaderVector headers_;
};
} // namespace net
#endif // NET_HTTP_HTTP_REQUEST_HEADERS_H_