mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 22:36:09 +03:00
120 lines
3.9 KiB
C++
120 lines
3.9 KiB
C++
// 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.
|
|
|
|
#include "net/http/http_vary_data.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "base/pickle.h"
|
|
#include "base/strings/string_util.h"
|
|
#include "net/http/http_request_headers.h"
|
|
#include "net/http/http_request_info.h"
|
|
#include "net/http/http_response_headers.h"
|
|
#include "net/http/http_util.h"
|
|
|
|
namespace net {
|
|
|
|
HttpVaryData::HttpVaryData() : is_valid_(false) {
|
|
}
|
|
|
|
bool HttpVaryData::Init(const HttpRequestInfo& request_info,
|
|
const HttpResponseHeaders& response_headers) {
|
|
base::MD5Context ctx;
|
|
base::MD5Init(&ctx);
|
|
|
|
is_valid_ = false;
|
|
bool processed_header = false;
|
|
|
|
// Feed the MD5 context in the order of the Vary header enumeration. If the
|
|
// Vary header repeats a header name, then that's OK.
|
|
//
|
|
// If the Vary header contains '*' then we can just notice it based on
|
|
// |cached_response_headers| in MatchesRequest(), and don't have to worry
|
|
// about the specific headers. We still want an HttpVaryData around, to let
|
|
// us handle this case. See section 4.1 of RFC 7234.
|
|
//
|
|
size_t iter = 0;
|
|
std::string name = "vary", request_header;
|
|
while (response_headers.EnumerateHeader(&iter, name, &request_header)) {
|
|
if (request_header == "*") {
|
|
// What's in request_digest_ will never be looked at, but make it
|
|
// deterministic so we don't serialize out uninitialized memory content.
|
|
memset(&request_digest_, 0, sizeof(request_digest_));
|
|
return is_valid_ = true;
|
|
}
|
|
AddField(request_info, request_header, &ctx);
|
|
processed_header = true;
|
|
}
|
|
|
|
if (!processed_header)
|
|
return false;
|
|
|
|
base::MD5Final(&request_digest_, &ctx);
|
|
return is_valid_ = true;
|
|
}
|
|
|
|
bool HttpVaryData::InitFromPickle(base::PickleIterator* iter) {
|
|
is_valid_ = false;
|
|
const char* data;
|
|
if (iter->ReadBytes(&data, sizeof(request_digest_))) {
|
|
memcpy(&request_digest_, data, sizeof(request_digest_));
|
|
return is_valid_ = true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void HttpVaryData::Persist(base::Pickle* pickle) const {
|
|
DCHECK(is_valid());
|
|
pickle->WriteBytes(&request_digest_, sizeof(request_digest_));
|
|
}
|
|
|
|
bool HttpVaryData::MatchesRequest(
|
|
const HttpRequestInfo& request_info,
|
|
const HttpResponseHeaders& cached_response_headers) const {
|
|
// Vary: * never matches.
|
|
if (cached_response_headers.HasHeaderValue("vary", "*"))
|
|
return false;
|
|
|
|
HttpVaryData new_vary_data;
|
|
if (!new_vary_data.Init(request_info, cached_response_headers)) {
|
|
// This case can happen if |this| was loaded from a cache that was populated
|
|
// by a build before crbug.com/469675 was fixed.
|
|
return false;
|
|
}
|
|
return memcmp(&new_vary_data.request_digest_, &request_digest_,
|
|
sizeof(request_digest_)) == 0;
|
|
}
|
|
|
|
// static
|
|
std::string HttpVaryData::GetRequestValue(
|
|
const HttpRequestInfo& request_info,
|
|
const std::string& request_header) {
|
|
// Unfortunately, we do not have access to all of the request headers at this
|
|
// point. Most notably, we do not have access to an Authorization header if
|
|
// one will be added to the request.
|
|
|
|
std::string result;
|
|
if (request_info.extra_headers.GetHeader(request_header, &result))
|
|
return result;
|
|
|
|
return std::string();
|
|
}
|
|
|
|
// static
|
|
void HttpVaryData::AddField(const HttpRequestInfo& request_info,
|
|
const std::string& request_header,
|
|
base::MD5Context* ctx) {
|
|
std::string request_value = GetRequestValue(request_info, request_header);
|
|
|
|
// Append a character that cannot appear in the request header line so that we
|
|
// protect against case where the concatenation of two request headers could
|
|
// look the same for a variety of values for the individual request headers.
|
|
// For example, "foo: 12\nbar: 3" looks like "foo: 1\nbar: 23" otherwise.
|
|
request_value.append(1, '\n');
|
|
|
|
base::MD5Update(ctx, request_value);
|
|
}
|
|
|
|
} // namespace net
|