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/spdy/core/http2_header_block.h" 20 #include "quiche/spdy/core/spdy_framer.h" 21 22 namespace quic { 23 24 // In-memory cache for HTTP responses. 25 // Reads from disk cache generated by: 26 // `wget -p --save_headers <url>` 27 class 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 file_name()45 const std::string& file_name() { return file_name_; } 46 host()47 absl::string_view host() { return host_; } 48 path()49 absl::string_view path() { return path_; } 50 spdy_headers()51 const spdy::Http2HeaderBlock& spdy_headers() { return spdy_headers_; } 52 body()53 absl::string_view body() { return body_; } 54 push_urls()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|. 83 void AddSimpleResponse(absl::string_view host, absl::string_view path, 84 int response_code, absl::string_view body); 85 86 // Add a response to the cache. 87 void AddResponse(absl::string_view host, absl::string_view path, 88 spdy::Http2HeaderBlock response_headers, 89 absl::string_view response_body); 90 91 // Add a response, with trailers, to the cache. 92 void AddResponse(absl::string_view host, absl::string_view path, 93 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( 99 absl::string_view host, absl::string_view path, 100 spdy::Http2HeaderBlock response_headers, absl::string_view response_body, 101 const std::vector<spdy::Http2HeaderBlock>& early_hints); 102 103 // Simulate a special behavior at a particular path. 104 void AddSpecialResponse( 105 absl::string_view host, absl::string_view path, 106 QuicBackendResponse::SpecialResponseType response_type); 107 108 void AddSpecialResponse( 109 absl::string_view host, absl::string_view path, 110 spdy::Http2HeaderBlock response_headers, absl::string_view response_body, 111 QuicBackendResponse::SpecialResponseType response_type); 112 113 // 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 119 // 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 129 // 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; SupportsWebTransport()142 bool SupportsWebTransport() override { return enable_webtransport_; } 143 144 private: 145 void AddResponseImpl(absl::string_view host, absl::string_view path, 146 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 154 // 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 166 // 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_ 177