blob: 8b4a64de8385812b756310e8cbef4715135c67d4 [file] [log] [blame]
// Copyright (c) 2016 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/spdy/spdy_header_indexing.h"
#include "net/spdy/spdy_bug_tracker.h"
using base::StringPiece;
namespace net {
int32_t FLAGS_gfe_spdy_indexing_set_bound = 300;
int32_t FLAGS_gfe_spdy_tracking_set_bound = 2000;
HeaderIndexing::HeaderIndexing()
: indexing_set_bound_(FLAGS_gfe_spdy_indexing_set_bound),
tracking_set_bound_(FLAGS_gfe_spdy_tracking_set_bound) {
SPDY_BUG_IF(indexing_set_bound_ >= tracking_set_bound_)
<< "Tracking set should be larger than indexing set";
}
HeaderIndexing::~HeaderIndexing() {}
void HeaderIndexing::CreateInitIndexingHeaders() {
const std::string initial_fields[] = {
// Estimated top 100 fields.
"alt-svc",
"date",
"cache-control",
"content-type",
"expires",
"location",
"x-xss-protection",
"p3p",
"set-cookie",
"alternate-protocol",
"last-modified",
"server",
"x-snapchat-request-id",
"content-disposition",
"strict-transport-security",
"x-content-type-options",
"content-security-policy",
"x-frame-options",
"x-snapchat-notice",
"pragma",
":status",
"content-length",
"etag",
"x-cloud-trace-context",
"vary",
"access-control-expose-headers",
"content-encoding",
"access-control-allow-origin",
"age",
":protocol",
"via",
"x-robots-tag",
"link",
"access-control-allow-headers",
"x-google-session-info",
"x-google-backends",
"x-google-gfe-request-trace",
"warning",
"x-guploader-uploadid",
"x-cup-server-proof",
"timing-allow-origin",
"x-google-trace",
"access-control-allow-credentials",
"google-delayed-impression",
"google-creative-id",
"access-control-allow-methods",
"x-ua-compatible",
"x-google-gfe-response-code-details-trace",
"google-lineitem-id",
"version",
"x-google-dos-service-trace",
"x-google-service",
"x-google-gfe-service-trace",
"sane-time-millis",
"x-google-netmon-label",
"x-google-apiary-auth-scopes",
"x-seed-signature",
"content-security-policy-report-only",
"x-auto-login",
"x-original-content-length",
"accept-ranges",
"x-goog-hash",
"x-google-gfe-response-body-transformations",
"cf-ray",
"x-content-security-policy-report-only",
"x-google-shellfish-status",
"x-amz-id-2",
"get-dictionary",
"grpc-message",
"x-hw",
"x-google-gfe-backend-request-info",
"x-goog-upload-header-x-google-session-info",
"x-amz-cf-id",
"x-powered-by",
"www-authenticate",
"access-control-max-age",
"x-spf-response-type",
"x-goog-meta-encoded_request",
"x-goog-generation",
"x-google-gslb-service",
"x-google-servertype",
"x-cache",
"x-chromium-appcache-fallback-override",
"x-goog-upload-url",
"x-goog-upload-control-url",
"content-range",
"x-seen-by",
"x-google-apps-framework-action",
"content-location",
"x-daystart",
"x-varnish",
"fastly-debug-digest",
"x-daynum",
"x-goog-stored-content-encoding",
"x-goog-storage-class",
"x-google-cookies-blocked",
"x-range-md5",
"x-served-by",
"x-client-wire-protocol",
"content-language",
};
indexing_set_.clear();
indexing_set_ =
HeaderSet(initial_fields, initial_fields + arraysize(initial_fields));
tracking_set_ =
HeaderSet(initial_fields, initial_fields + arraysize(initial_fields));
}
bool HeaderIndexing::ShouldIndex(StringPiece header, StringPiece /* value */) {
if (header.empty()) {
return false;
}
// header is in indexing set.
std::string header_str(header.data(), header.size());
if (indexing_set_.find(header_str) != indexing_set_.end()) {
return true;
}
// header not in indexing set. Check tracking set.
if (tracking_set_.find(header_str) != tracking_set_.end()) {
// Seen this header before. Add it to indexing set.
TryInsertHeader(std::move(header_str), &indexing_set_, indexing_set_bound_);
} else {
// Add header to tracking set.
TryInsertHeader(std::move(header_str), &tracking_set_, tracking_set_bound_);
}
return false;
}
void HeaderIndexing::TryInsertHeader(std::string&& header,
HeaderSet* set,
size_t bound) {
std::pair<HeaderSet::iterator, bool> result = set->insert(std::move(header));
if (set->size() > bound) {
// Reach the size limit. Remove the header next to the newly added header.
// If the new header is at the end, look for the "next" element at the
// beginning.
HeaderSet::iterator it = std::next(result.first);
if (it != set->end()) {
set->erase(it);
} else {
set->erase(set->begin());
}
}
}
} // namespace net