blob: 930ef5841b45f6d20e90d35bd2fa260e68097c4f [file] [log] [blame]
Bence Békybac04052022-04-07 15:44:29 -04001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
6#define QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_
7
8#include <list>
9#include <map>
10#include <memory>
11#include <vector>
12
13#include "absl/container/flat_hash_map.h"
14#include "absl/strings/string_view.h"
15#include "quiche/quic/core/http/spdy_utils.h"
Bence Békybac04052022-04-07 15:44:29 -040016#include "quiche/quic/platform/api/quic_mutex.h"
17#include "quiche/quic/tools/quic_backend_response.h"
18#include "quiche/quic/tools/quic_simple_server_backend.h"
bncffaa4c32022-07-18 08:29:54 -070019#include "quiche/spdy/core/http2_header_block.h"
Bence Békybac04052022-04-07 15:44:29 -040020#include "quiche/spdy/core/spdy_framer.h"
21
22namespace quic {
23
24// In-memory cache for HTTP responses.
25// Reads from disk cache generated by:
26// `wget -p --save_headers <url>`
27class QuicMemoryCacheBackend : public QuicSimpleServerBackend {
28 public:
29 // Class to manage loading a resource file into memory. There are
30 // two uses: called by InitializeBackend to load resources
31 // from files, and recursively called when said resources specify
32 // server push associations.
33 class ResourceFile {
34 public:
35 explicit ResourceFile(const std::string& file_name);
36 ResourceFile(const ResourceFile&) = delete;
37 ResourceFile& operator=(const ResourceFile&) = delete;
38 virtual ~ResourceFile();
39
40 void Read();
41
42 // |base| is |file_name_| with |cache_directory| prefix stripped.
43 void SetHostPathFromBase(absl::string_view base);
44
45 const std::string& file_name() { return file_name_; }
46
47 absl::string_view host() { return host_; }
48
49 absl::string_view path() { return path_; }
50
51 const spdy::Http2HeaderBlock& spdy_headers() { return spdy_headers_; }
52
53 absl::string_view body() { return body_; }
54
55 const std::vector<absl::string_view>& push_urls() { return push_urls_; }
56
57 private:
58 void HandleXOriginalUrl();
59 absl::string_view RemoveScheme(absl::string_view url);
60
61 std::string file_name_;
62 std::string file_contents_;
63 absl::string_view body_;
64 spdy::Http2HeaderBlock spdy_headers_;
65 absl::string_view x_original_url_;
66 std::vector<absl::string_view> push_urls_;
67 std::string host_;
68 std::string path_;
69 };
70
71 QuicMemoryCacheBackend();
72 QuicMemoryCacheBackend(const QuicMemoryCacheBackend&) = delete;
73 QuicMemoryCacheBackend& operator=(const QuicMemoryCacheBackend&) = delete;
74 ~QuicMemoryCacheBackend() override;
75
76 // Retrieve a response from this cache for a given host and path..
77 // If no appropriate response exists, nullptr is returned.
78 const QuicBackendResponse* GetResponse(absl::string_view host,
79 absl::string_view path) const;
80
81 // Adds a simple response to the cache. The response headers will
82 // only contain the "content-length" header with the length of |body|.
bncbd76ad82022-04-13 08:30:34 -070083 void AddSimpleResponse(absl::string_view host, absl::string_view path,
84 int response_code, absl::string_view body);
Bence Békybac04052022-04-07 15:44:29 -040085
Bence Békybac04052022-04-07 15:44:29 -040086 // Add a response to the cache.
bncbd76ad82022-04-13 08:30:34 -070087 void AddResponse(absl::string_view host, absl::string_view path,
Bence Békybac04052022-04-07 15:44:29 -040088 spdy::Http2HeaderBlock response_headers,
89 absl::string_view response_body);
90
91 // Add a response, with trailers, to the cache.
bncbd76ad82022-04-13 08:30:34 -070092 void AddResponse(absl::string_view host, absl::string_view path,
Bence Békybac04052022-04-07 15:44:29 -040093 spdy::Http2HeaderBlock response_headers,
94 absl::string_view response_body,
95 spdy::Http2HeaderBlock response_trailers);
96
97 // Add a response, with 103 Early Hints, to the cache.
98 void AddResponseWithEarlyHints(
bncbd76ad82022-04-13 08:30:34 -070099 absl::string_view host, absl::string_view path,
100 spdy::Http2HeaderBlock response_headers, absl::string_view response_body,
Bence Békybac04052022-04-07 15:44:29 -0400101 const std::vector<spdy::Http2HeaderBlock>& early_hints);
102
103 // Simulate a special behavior at a particular path.
104 void AddSpecialResponse(
bncbd76ad82022-04-13 08:30:34 -0700105 absl::string_view host, absl::string_view path,
Bence Békybac04052022-04-07 15:44:29 -0400106 QuicBackendResponse::SpecialResponseType response_type);
107
108 void AddSpecialResponse(
bncbd76ad82022-04-13 08:30:34 -0700109 absl::string_view host, absl::string_view path,
110 spdy::Http2HeaderBlock response_headers, absl::string_view response_body,
Bence Békybac04052022-04-07 15:44:29 -0400111 QuicBackendResponse::SpecialResponseType response_type);
112
QUICHE team3ea648e2022-08-16 22:34:53 -0700113 // Finds a response with the given host and path, and assign it a simulated
114 // delay. Returns true if the requisite response was found and the delay was
115 // set.
116 bool SetResponseDelay(absl::string_view host, absl::string_view path,
117 QuicTime::Delta delay);
118
Bence Békybac04052022-04-07 15:44:29 -0400119 // Sets a default response in case of cache misses. Takes ownership of
120 // 'response'.
121 void AddDefaultResponse(QuicBackendResponse* response);
122
123 // Once called, URLs which have a numeric path will send a dynamically
124 // generated response of that many bytes.
125 void GenerateDynamicResponses();
126
127 void EnableWebTransport();
128
Bence Békybac04052022-04-07 15:44:29 -0400129 // Implements the functions for interface QuicSimpleServerBackend
130 // |cache_cirectory| can be generated using `wget -p --save-headers <url>`.
131 bool InitializeBackend(const std::string& cache_directory) override;
132 bool IsBackendInitialized() const override;
133 void FetchResponseFromBackend(
134 const spdy::Http2HeaderBlock& request_headers,
135 const std::string& request_body,
136 QuicSimpleServerBackend::RequestHandler* quic_stream) override;
137 void CloseBackendResponseStream(
138 QuicSimpleServerBackend::RequestHandler* quic_stream) override;
139 WebTransportResponse ProcessWebTransportRequest(
140 const spdy::Http2HeaderBlock& request_headers,
141 WebTransportSession* session) override;
142 bool SupportsWebTransport() override { return enable_webtransport_; }
143
144 private:
bncbd76ad82022-04-13 08:30:34 -0700145 void AddResponseImpl(absl::string_view host, absl::string_view path,
Bence Békybac04052022-04-07 15:44:29 -0400146 QuicBackendResponse::SpecialResponseType response_type,
147 spdy::Http2HeaderBlock response_headers,
148 absl::string_view response_body,
149 spdy::Http2HeaderBlock response_trailers,
150 const std::vector<spdy::Http2HeaderBlock>& early_hints);
151
152 std::string GetKey(absl::string_view host, absl::string_view path) const;
153
Bence Békybac04052022-04-07 15:44:29 -0400154 // Cached responses.
155 absl::flat_hash_map<std::string, std::unique_ptr<QuicBackendResponse>>
156 responses_ QUIC_GUARDED_BY(response_mutex_);
157
158 // The default response for cache misses, if set.
159 std::unique_ptr<QuicBackendResponse> default_response_
160 QUIC_GUARDED_BY(response_mutex_);
161
162 // The generate bytes response, if set.
163 std::unique_ptr<QuicBackendResponse> generate_bytes_response_
164 QUIC_GUARDED_BY(response_mutex_);
165
Bence Békybac04052022-04-07 15:44:29 -0400166 // Protects against concurrent access from test threads setting responses, and
167 // server threads accessing those responses.
168 mutable QuicMutex response_mutex_;
169 bool cache_initialized_;
170
171 bool enable_webtransport_ = false;
172};
173
174} // namespace quic
175
176#endif // QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_