| Index: net/tools/quic/quic_in_memory_cache.cc
|
| diff --git a/net/tools/quic/quic_in_memory_cache.cc b/net/tools/quic/quic_in_memory_cache.cc
|
| index 1f31b9cfe1362dc6a14a4e673ea4fbf68d90e6ec..aa45d2f855346b230d99ca477ee93a8a4beecaed 100644
|
| --- a/net/tools/quic/quic_in_memory_cache.cc
|
| +++ b/net/tools/quic/quic_in_memory_cache.cc
|
| @@ -22,6 +22,62 @@ using std::string;
|
|
|
| namespace net {
|
|
|
| +namespace {
|
| +
|
| +class ResourceFileImpl : public net::QuicInMemoryCache::ResourceFile {
|
| + public:
|
| + ResourceFileImpl(const base::FilePath& file_name) : ResourceFile(file_name) {}
|
| +
|
| + void Read() override {
|
| + base::ReadFileToString(FilePath(file_name_), &file_contents_);
|
| +
|
| + int file_len = static_cast<int>(file_contents_.length());
|
| + int headers_end =
|
| + HttpUtil::LocateEndOfHeaders(file_contents_.data(), file_len);
|
| + if (headers_end < 1) {
|
| + LOG(DFATAL) << "Headers invalid or empty, ignoring: "
|
| + << file_name_.value();
|
| + return;
|
| + }
|
| + http_headers_ = new HttpResponseHeaders(
|
| + HttpUtil::AssembleRawHeaders(file_contents_.data(), headers_end));
|
| +
|
| + if (http_headers_->GetNormalizedHeader("X-Original-Url", &url_)) {
|
| + x_original_url_ = StringPiece(url_);
|
| + HandleXOriginalUrl();
|
| + }
|
| +
|
| + // X-Push-URL header is a relatively quick way to support sever push
|
| + // in the toy server. A production server should use link=preload
|
| + // stuff as described in https://w3c.github.io/preload/.
|
| + StringPiece x_push_url("X-Push-Url");
|
| + if (http_headers_->HasHeader(x_push_url)) {
|
| + size_t iter = 0;
|
| + std::unique_ptr<std::string> push_url(new string());
|
| + while (
|
| + http_headers_->EnumerateHeader(&iter, x_push_url, push_url.get())) {
|
| + push_urls_.push_back(StringPiece(*push_url));
|
| + push_url_values_.push_back(std::move(push_url));
|
| + push_url.reset(new string());
|
| + }
|
| + }
|
| +
|
| + body_ = StringPiece(file_contents_.data() + headers_end,
|
| + file_contents_.size() - headers_end);
|
| +
|
| + CreateSpdyHeadersFromHttpResponse(*http_headers_, HTTP2, &spdy_headers_);
|
| + }
|
| +
|
| + private:
|
| + scoped_refptr<HttpResponseHeaders> http_headers_;
|
| + std::string url_;
|
| + std::list<std::unique_ptr<string>> push_url_values_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ResourceFileImpl);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| QuicInMemoryCache::ServerPushInfo::ServerPushInfo(
|
| GURL request_url,
|
| const SpdyHeaderBlock& headers,
|
| @@ -39,6 +95,39 @@ QuicInMemoryCache::Response::Response() : response_type_(REGULAR_RESPONSE) {}
|
|
|
| QuicInMemoryCache::Response::~Response() {}
|
|
|
| +QuicInMemoryCache::ResourceFile::ResourceFile(const base::FilePath& file_name)
|
| + : file_name_(file_name), file_name_string_(file_name.AsUTF8Unsafe()) {}
|
| +
|
| +QuicInMemoryCache::ResourceFile::~ResourceFile() {}
|
| +
|
| +void QuicInMemoryCache::ResourceFile::SetHostPathFromBase(StringPiece base) {
|
| + size_t path_start = base.find_first_of('/');
|
| + DCHECK_LT(0UL, path_start);
|
| + host_ = base.substr(0, path_start);
|
| + size_t query_start = base.find_first_of(',');
|
| + if (query_start > 0) {
|
| + path_ = base.substr(path_start, query_start - 1);
|
| + } else {
|
| + path_ = base.substr(path_start);
|
| + }
|
| +}
|
| +
|
| +StringPiece QuicInMemoryCache::ResourceFile::RemoveScheme(StringPiece url) {
|
| + if (url.starts_with("https://")) {
|
| + url.remove_prefix(8);
|
| + } else if (url.starts_with("http://")) {
|
| + url.remove_prefix(7);
|
| + }
|
| + return url;
|
| +}
|
| +
|
| +void QuicInMemoryCache::ResourceFile::HandleXOriginalUrl() {
|
| + StringPiece url(x_original_url_);
|
| + // Remove the protocol so we can add it below.
|
| + url = RemoveScheme(url);
|
| + SetHostPathFromBase(url);
|
| +}
|
| +
|
| // static
|
| QuicInMemoryCache* QuicInMemoryCache::GetInstance() {
|
| return base::Singleton<QuicInMemoryCache>::get();
|
| @@ -126,7 +215,7 @@ void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) {
|
| << cache_directory;
|
| FilePath directory(FilePath::FromUTF8Unsafe(cache_directory));
|
| base::FileEnumerator file_list(directory, true, base::FileEnumerator::FILES);
|
| -
|
| + list<std::unique_ptr<ResourceFile>> resource_files;
|
| for (FilePath file_iter = file_list.Next(); !file_iter.empty();
|
| file_iter = file_list.Next()) {
|
| // Need to skip files in .svn directories
|
| @@ -134,55 +223,40 @@ void QuicInMemoryCache::InitializeFromDirectory(const string& cache_directory) {
|
| continue;
|
| }
|
|
|
| + std::unique_ptr<ResourceFile> resource_file(
|
| + new ResourceFileImpl(file_iter));
|
| +
|
| // Tease apart filename into host and path.
|
| - string file = file_iter.AsUTF8Unsafe();
|
| - file.erase(0, cache_directory.length());
|
| - if (file[0] == '/') {
|
| - file.erase(0, 1);
|
| + StringPiece base(resource_file->file_name());
|
| + base.remove_prefix(cache_directory.length());
|
| + if (base[0] == '/') {
|
| + base.remove_prefix(1);
|
| }
|
|
|
| - string file_contents;
|
| - base::ReadFileToString(file_iter, &file_contents);
|
| - int file_len = static_cast<int>(file_contents.length());
|
| - int headers_end =
|
| - HttpUtil::LocateEndOfHeaders(file_contents.data(), file_len);
|
| - if (headers_end < 1) {
|
| - LOG(DFATAL) << "Headers invalid or empty, ignoring: " << file;
|
| - continue;
|
| - }
|
| + resource_file->SetHostPathFromBase(base);
|
| + resource_file->Read();
|
|
|
| - string raw_headers =
|
| - HttpUtil::AssembleRawHeaders(file_contents.data(), headers_end);
|
| -
|
| - scoped_refptr<HttpResponseHeaders> response_headers =
|
| - new HttpResponseHeaders(raw_headers);
|
| -
|
| - string base;
|
| - if (response_headers->GetNormalizedHeader("X-Original-Url", &base)) {
|
| - response_headers->RemoveHeader("X-Original-Url");
|
| - // Remove the protocol so we can add it below.
|
| - if (base::StartsWith(base, "https://",
|
| - base::CompareCase::INSENSITIVE_ASCII)) {
|
| - base = base.substr(8);
|
| - } else if (base::StartsWith(base, "http://",
|
| - base::CompareCase::INSENSITIVE_ASCII)) {
|
| - base = base.substr(7);
|
| - }
|
| - } else {
|
| - base = file;
|
| - }
|
| + AddResponse(resource_file->host(), resource_file->path(),
|
| + resource_file->spdy_headers(), resource_file->body());
|
| +
|
| + resource_files.push_back(std::move(resource_file));
|
| + }
|
|
|
| - size_t path_start = base.find_first_of('/');
|
| - StringPiece host(StringPiece(base).substr(0, path_start));
|
| - StringPiece path(StringPiece(base).substr(path_start));
|
| - if (path.back() == ',') {
|
| - path.remove_suffix(1);
|
| + for (const auto& resource_file : resource_files) {
|
| + list<ServerPushInfo> push_resources;
|
| + for (const auto& push_url : resource_file->push_urls()) {
|
| + GURL url(push_url);
|
| + const Response* response = GetResponse(url.host(), url.path());
|
| + if (!response) {
|
| + QUIC_BUG << "Push URL '" << push_url << "' not found.";
|
| + return;
|
| + }
|
| + push_resources.push_back(ServerPushInfo(url, response->headers(),
|
| + net::kV3LowestPriority,
|
| + response->body().as_string()));
|
| }
|
| - StringPiece body(file_contents.data() + headers_end,
|
| - file_contents.size() - headers_end);
|
| - SpdyHeaderBlock header_block;
|
| - CreateSpdyHeadersFromHttpResponse(*response_headers, HTTP2, &header_block);
|
| - AddResponse(host, path, header_block, body);
|
| + MaybeAddServerPushResources(resource_file->host(), resource_file->path(),
|
| + push_resources);
|
| }
|
| }
|
|
|
| @@ -193,6 +267,8 @@ list<ServerPushInfo> QuicInMemoryCache::GetServerPushResources(
|
| for (auto it = resource_range.first; it != resource_range.second; ++it) {
|
| resources.push_back(it->second);
|
| }
|
| + DVLOG(1) << "Found " << resources.size() << " push resources for "
|
| + << request_url;
|
| return resources;
|
| }
|
|
|
| @@ -218,6 +294,7 @@ void QuicInMemoryCache::AddResponseImpl(
|
| new_response->set_headers(response_headers);
|
| new_response->set_body(response_body);
|
| new_response->set_trailers(response_trailers);
|
| + DVLOG(1) << "Add response with key " << key;
|
| responses_[key] = new_response;
|
| }
|
|
|
| @@ -229,14 +306,16 @@ void QuicInMemoryCache::MaybeAddServerPushResources(
|
| StringPiece request_host,
|
| StringPiece request_path,
|
| list<ServerPushInfo> push_resources) {
|
| - string request_url = request_host.as_string() + request_path.as_string();
|
| + string request_url = GetKey(request_host, request_path);
|
|
|
| for (const auto& push_resource : push_resources) {
|
| if (PushResourceExistsInCache(request_url, push_resource)) {
|
| continue;
|
| }
|
|
|
| - DVLOG(1) << "Add request-resource association.";
|
| + DVLOG(1) << "Add request-resource association: request url " << request_url
|
| + << " push url " << push_resource.request_url
|
| + << " response headers " << push_resource.headers.DebugString();
|
| server_push_resources_.insert(std::make_pair(request_url, push_resource));
|
| string host = push_resource.request_url.host();
|
| if (host.empty()) {
|
| @@ -248,7 +327,7 @@ void QuicInMemoryCache::MaybeAddServerPushResources(
|
| SpdyHeaderBlock headers = push_resource.headers;
|
| StringPiece body = push_resource.body;
|
| DVLOG(1) << "Add response for push resource: host " << host << " path "
|
| - << path << " body " << body;
|
| + << path;
|
| AddResponse(host, path, headers, body);
|
| }
|
| }
|
|
|