1 // 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" 16 #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" 19 #include "quiche/quic/tools/quic_url.h" 20 #include "quiche/spdy/core/http2_header_block.h" 21 #include "quiche/spdy/core/spdy_framer.h" 22 23 namespace quic { 24 25 // In-memory cache for HTTP responses. 26 // Reads from disk cache generated by: 27 // `wget -p --save_headers <url>` 28 class QuicMemoryCacheBackend : public QuicSimpleServerBackend { 29 public: 30 // Class to manage loading a resource file into memory. There are 31 // two uses: called by InitializeBackend to load resources 32 // from files, and recursively called when said resources specify 33 // server push associations. 34 class ResourceFile { 35 public: 36 explicit ResourceFile(const std::string& file_name); 37 ResourceFile(const ResourceFile&) = delete; 38 ResourceFile& operator=(const ResourceFile&) = delete; 39 virtual ~ResourceFile(); 40 41 void Read(); 42 43 // |base| is |file_name_| with |cache_directory| prefix stripped. 44 void SetHostPathFromBase(absl::string_view base); 45 file_name()46 const std::string& file_name() { return file_name_; } 47 host()48 absl::string_view host() { return host_; } 49 path()50 absl::string_view path() { return path_; } 51 spdy_headers()52 const spdy::Http2HeaderBlock& spdy_headers() { return spdy_headers_; } 53 body()54 absl::string_view body() { return body_; } 55 push_urls()56 const std::vector<absl::string_view>& push_urls() { return push_urls_; } 57 58 private: 59 void HandleXOriginalUrl(); 60 absl::string_view RemoveScheme(absl::string_view url); 61 62 std::string file_name_; 63 std::string file_contents_; 64 absl::string_view body_; 65 spdy::Http2HeaderBlock spdy_headers_; 66 absl::string_view x_original_url_; 67 std::vector<absl::string_view> push_urls_; 68 std::string host_; 69 std::string path_; 70 }; 71 72 QuicMemoryCacheBackend(); 73 QuicMemoryCacheBackend(const QuicMemoryCacheBackend&) = delete; 74 QuicMemoryCacheBackend& operator=(const QuicMemoryCacheBackend&) = delete; 75 ~QuicMemoryCacheBackend() override; 76 77 // Retrieve a response from this cache for a given host and path.. 78 // If no appropriate response exists, nullptr is returned. 79 const QuicBackendResponse* GetResponse(absl::string_view host, 80 absl::string_view path) const; 81 82 // Adds a simple response to the cache. The response headers will 83 // only contain the "content-length" header with the length of |body|. 84 void AddSimpleResponse(absl::string_view host, absl::string_view path, 85 int response_code, absl::string_view body); 86 87 // Add a simple response to the cache as AddSimpleResponse() does, and add 88 // some server push resources(resource path, corresponding response status and 89 // path) associated with it. 90 // Push resource implicitly come from the same host. 91 // TODO(b/171463363): Remove. 92 void AddSimpleResponseWithServerPushResources( 93 absl::string_view host, absl::string_view path, int response_code, 94 absl::string_view body, 95 std::list<QuicBackendResponse::ServerPushInfo> push_resources); 96 97 // Add a response to the cache. 98 void AddResponse(absl::string_view host, absl::string_view path, 99 spdy::Http2HeaderBlock response_headers, 100 absl::string_view response_body); 101 102 // Add a response, with trailers, to the cache. 103 void AddResponse(absl::string_view host, absl::string_view path, 104 spdy::Http2HeaderBlock response_headers, 105 absl::string_view response_body, 106 spdy::Http2HeaderBlock response_trailers); 107 108 // Add a response, with 103 Early Hints, to the cache. 109 void AddResponseWithEarlyHints( 110 absl::string_view host, absl::string_view path, 111 spdy::Http2HeaderBlock response_headers, absl::string_view response_body, 112 const std::vector<spdy::Http2HeaderBlock>& early_hints); 113 114 // Simulate a special behavior at a particular path. 115 void AddSpecialResponse( 116 absl::string_view host, absl::string_view path, 117 QuicBackendResponse::SpecialResponseType response_type); 118 119 void AddSpecialResponse( 120 absl::string_view host, absl::string_view path, 121 spdy::Http2HeaderBlock response_headers, absl::string_view response_body, 122 QuicBackendResponse::SpecialResponseType response_type); 123 124 // Finds a response with the given host and path, and assign it a simulated 125 // delay. Returns true if the requisite response was found and the delay was 126 // set. 127 bool SetResponseDelay(absl::string_view host, absl::string_view path, 128 QuicTime::Delta delay); 129 130 // Sets a default response in case of cache misses. Takes ownership of 131 // 'response'. 132 void AddDefaultResponse(QuicBackendResponse* response); 133 134 // Once called, URLs which have a numeric path will send a dynamically 135 // generated response of that many bytes. 136 void GenerateDynamicResponses(); 137 138 void EnableWebTransport(); 139 140 // Find all the server push resources associated with |request_url|. 141 // TODO(b/171463363): Remove. 142 std::list<QuicBackendResponse::ServerPushInfo> GetServerPushResources( 143 std::string request_url); 144 145 // Implements the functions for interface QuicSimpleServerBackend 146 // |cache_cirectory| can be generated using `wget -p --save-headers <url>`. 147 bool InitializeBackend(const std::string& cache_directory) override; 148 bool IsBackendInitialized() const override; 149 void FetchResponseFromBackend( 150 const spdy::Http2HeaderBlock& request_headers, 151 const std::string& request_body, 152 QuicSimpleServerBackend::RequestHandler* quic_stream) override; 153 void CloseBackendResponseStream( 154 QuicSimpleServerBackend::RequestHandler* quic_stream) override; 155 WebTransportResponse ProcessWebTransportRequest( 156 const spdy::Http2HeaderBlock& request_headers, 157 WebTransportSession* session) override; SupportsWebTransport()158 bool SupportsWebTransport() override { return enable_webtransport_; } 159 160 private: 161 void AddResponseImpl(absl::string_view host, absl::string_view path, 162 QuicBackendResponse::SpecialResponseType response_type, 163 spdy::Http2HeaderBlock response_headers, 164 absl::string_view response_body, 165 spdy::Http2HeaderBlock response_trailers, 166 const std::vector<spdy::Http2HeaderBlock>& early_hints); 167 168 std::string GetKey(absl::string_view host, absl::string_view path) const; 169 170 // Add some server push urls with given responses for specified 171 // request if these push resources are not associated with this request yet. 172 // TODO(b/171463363): Remove. 173 void MaybeAddServerPushResources( 174 absl::string_view request_host, absl::string_view request_path, 175 std::list<QuicBackendResponse::ServerPushInfo> push_resources); 176 177 // Check if push resource(push_host/push_path) associated with given request 178 // url already exists in server push map. 179 // TODO(b/171463363): Remove. 180 bool PushResourceExistsInCache(std::string original_request_url, 181 QuicBackendResponse::ServerPushInfo resource); 182 183 // Cached responses. 184 absl::flat_hash_map<std::string, std::unique_ptr<QuicBackendResponse>> 185 responses_ QUIC_GUARDED_BY(response_mutex_); 186 187 // The default response for cache misses, if set. 188 std::unique_ptr<QuicBackendResponse> default_response_ 189 QUIC_GUARDED_BY(response_mutex_); 190 191 // The generate bytes response, if set. 192 std::unique_ptr<QuicBackendResponse> generate_bytes_response_ 193 QUIC_GUARDED_BY(response_mutex_); 194 195 // A map from request URL to associated server push responses (if any). 196 // TODO(b/171463363): Remove. 197 std::multimap<std::string, QuicBackendResponse::ServerPushInfo> 198 server_push_resources_ QUIC_GUARDED_BY(response_mutex_); 199 200 // Protects against concurrent access from test threads setting responses, and 201 // server threads accessing those responses. 202 mutable QuicMutex response_mutex_; 203 bool cache_initialized_; 204 205 bool enable_webtransport_ = false; 206 }; 207 208 } // namespace quic 209 210 #endif // QUICHE_QUIC_TOOLS_QUIC_MEMORY_CACHE_BACKEND_H_ 211