Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Cache.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_IO_Network_Transfer_Cache_h_
5#define _Stroika_Foundation_IO_Network_Transfer_Cache_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
10#include "Stroika/Foundation/Containers/Set.h"
13
14#include "Request.h"
15#include "Response.h"
16
17/**
18 *
19 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
20 *
21 * This cache is a generic HTTP fetch cache API, allowing users of the IO::Transfer::Connection code to
22 * use different cache implementations (e.g. one storing to disk, and one to RAM).
23 *
24 * It is hopefully done in such a way that you can do alot of code sharing among these implementations,
25 * but do not need to.
26 *
27 * This Cache class also comes with an opaque, one-size-fits all (who they kidding) implementation, with a
28 * handful of configuration options.
29 */
30
32
33 struct IRep;
34
35 struct Ptr;
36
37 struct Element;
38
39 struct EvalContext;
40
41 /**
42 */
43 struct DefaultOptions {
44 DefaultOptions () = default;
45
46 optional<size_t> fCacheSize;
47
48 /**
49 * if not specified via expires header, or max-age etc...
50 */
51 optional<Time::Duration> fDefaultResourceTTL;
52
53 /**
54 */
55 static const inline String kCachedResultHeaderDefault{"X-Stroika-Cached-Result"sv};
56
57 /**
58 * This header will always appear in cached results (so the caller can tell a Response is 'from cache').
59 * If nullopt, the header will not be generated. It defaults to kCachedResultHeaderDefault.
60 */
61 optional<String> fCachedResultHeader{kCachedResultHeaderDefault};
62 };
63
64 /**
65 * Creates a default-styled HTTP cache object. Note - you still must associate this cache object with
66 * any cache connections you create (typically by assigning it to the Connection creation factory)
67 *
68 * NOTE - though the smart ptr Ptr is not fully re-entrant, the letter class created by CreateDefault is fully
69 * internally synchronized. This means you can re-use it with multiple connections and run those connection requests from as
70 * many threads as desired.
71 *
72 * @todo - redo with default argument, but messed up on gcc/clang/not sure why -- LGP 2019-06-27
73 * @todo - maybe rename New ()
74 */
75 Ptr CreateDefault ();
76 Ptr CreateDefault (const DefaultOptions& options);
77
78 /**
79 * This is the basic element of data stored in the cache for any cached URL. Some implementations may store more or less,
80 * But this provides the rough outline of what is expected to cache, and utility apis to extract the cache control policy data.
81 */
82 struct Element {
83 public:
84 Element () = default;
85 Element (const Response& response);
86
87 public:
88 virtual ~Element () = default;
89
90 public:
91 /**
92 */
93 nonvirtual Mapping<String, String> GetCombinedHeaders () const;
94
95 public:
96 /**
97 * Check - based on incoming http headers - whether this resoure is cachable.
98 */
99 virtual bool IsCachable () const;
100
101 public:
102 /**
103 * return nullopt if unknown (so invokes some sort of default)
104 *
105 * Invalid doesn't mean you must throw away. Just that you must validate (conditional get) to see if this can be re-used.
106 * This returns the amount of time you dont even need to bother revalidating with a conditional get.
107 */
108 virtual optional<Time::DateTime> IsValidUntil () const;
109
110 public:
111 /**
112 * @see Characters::ToString ();
113 */
114 nonvirtual String ToString () const;
115
116 public:
117 optional<String> fETag;
118 optional<Time::DateTime> fExpires;
119 optional<Time::DateTime> fExpiresDueToMaxAge;
120 optional<Time::DateTime> fLastModified;
121 optional<Containers::Set<String>> fCacheControl; // parsed/split rep
122 Memory::BLOB fBody; // no point in a cache entry without this
123 optional<DataExchange::InternetMediaType> fContentType;
124 Mapping<String, String> fOtherHeaders; // headers not captured/extracted above
125 };
126
127 /**
128 * Used internally by Connection::Rep subclasses to call the Cache::Rep API. The reason for this is we want some information
129 * snapshotted from before the request to be used after the request (when someone else may have deleted the item from the cache).
130 */
131 struct EvalContext {
132 EvalContext () = default;
133
134 optional<Element> fCachedElement;
135 optional<URI> fFullURI;
136 };
137
138 /**
139 */
140 struct IRep {
141
142 virtual ~IRep () = default;
143
144 /**
145 * was called BeforeGet - but can decide internally - and callers can decide to only use on get
146 */
147 virtual optional<Response> OnBeforeFetch (EvalContext* context, const URI& schemeAndAuthority, Request* request) noexcept = 0;
148
149 /**
150 * replaces response value with right answer on 304, and caches results from successful fetch calls.
151 * was called AfterGet
152 */
153 virtual void OnAfterFetch (const EvalContext& context, Response* response) noexcept = 0;
154
155 /**
156 * if not cleared, external cache can be re-used
157 */
158 virtual void ClearCache () = 0;
159
160 /**
161 */
162 virtual optional<Element> Lookup (const URI& url) const = 0;
163 };
164
165 /**
166 */
167 struct Ptr : shared_ptr<Cache::IRep> {};
168
169}
170
171/*
172 ********************************************************************************
173 ***************************** Implementation Details ***************************
174 ********************************************************************************
175 */
176#include "Cache.inl"
177
178#endif /*_Stroika_Foundation_IO_Network_Transfer_Cache_h_*/
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
virtual optional< Time::DateTime > IsValidUntil() const
Definition Cache.cpp:286