66
77#include < LibCrypto/Hash/SHA1.h>
88#include < LibURL/URL.h>
9+ #include < RequestServer/Cache/DiskCache.h>
910#include < RequestServer/Cache/Utilities.h>
1011
1112namespace RequestServer {
@@ -207,11 +208,12 @@ bool is_header_exempted_from_storage(StringView name)
207208
208209 // AD-HOC: Exclude headers used only for testing.
209210 TEST_CACHE_ENABLED_HEADER,
210- TEST_CACHE_STATUS_HEADER);
211+ TEST_CACHE_STATUS_HEADER,
212+ TEST_CACHE_REQUEST_TIME_OFFSET);
211213}
212214
213215// https://httpwg.org/specs/rfc9111.html#heuristic.freshness
214- static AK::Duration calculate_heuristic_freshness_lifetime (HTTP::HeaderMap const & headers)
216+ static AK::Duration calculate_heuristic_freshness_lifetime (HTTP::HeaderMap const & headers, AK::Duration current_time_offset_for_testing )
215217{
216218 // Since origin servers do not always provide explicit expiration times, a cache MAY assign a heuristic expiration
217219 // time when an explicit time is not specified, employing algorithms that use other field values (such as the
@@ -230,7 +232,7 @@ static AK::Duration calculate_heuristic_freshness_lifetime(HTTP::HeaderMap const
230232 if (!last_modified.has_value ())
231233 return {};
232234
233- auto now = UnixDateTime::now ();
235+ auto now = UnixDateTime::now () + current_time_offset_for_testing ;
234236 auto since_last_modified = now - *last_modified;
235237 auto seconds = since_last_modified.to_seconds ();
236238
@@ -243,7 +245,7 @@ static AK::Duration calculate_heuristic_freshness_lifetime(HTTP::HeaderMap const
243245}
244246
245247// https://httpwg.org/specs/rfc9111.html#calculating.freshness.lifetime
246- AK::Duration calculate_freshness_lifetime (u32 status_code, HTTP::HeaderMap const & headers)
248+ AK::Duration calculate_freshness_lifetime (u32 status_code, HTTP::HeaderMap const & headers, AK::Duration current_time_offset_for_testing )
247249{
248250 // A cache can calculate the freshness lifetime (denoted as freshness_lifetime) of a response by evaluating the
249251 // following rules and using the first match:
@@ -265,8 +267,8 @@ AK::Duration calculate_freshness_lifetime(u32 status_code, HTTP::HeaderMap const
265267 // * If the Expires response header field (Section 5.3) is present, use its value minus the value of the Date response
266268 // header field (using the time the message was received if it is not present, as per Section 6.6.1 of [HTTP]), or
267269 if (auto expires = parse_http_date (headers.get (" Expires" sv)); expires.has_value ()) {
268- auto date = parse_http_date (headers.get (" Date" sv)).value_or_lazy_evaluated ([]() {
269- return UnixDateTime::now ();
270+ auto date = parse_http_date (headers.get (" Date" sv)).value_or_lazy_evaluated ([& ]() {
271+ return UnixDateTime::now () + current_time_offset_for_testing ;
270272 });
271273
272274 return *expires - date;
@@ -287,14 +289,14 @@ AK::Duration calculate_freshness_lifetime(u32 status_code, HTTP::HeaderMap const
287289 }
288290
289291 if (heuristics_allowed)
290- return calculate_heuristic_freshness_lifetime (headers);
292+ return calculate_heuristic_freshness_lifetime (headers, current_time_offset_for_testing );
291293
292294 // No explicit expiration time, and heuristics not allowed or not applicable.
293295 return {};
294296}
295297
296298// https://httpwg.org/specs/rfc9111.html#age.calculations
297- AK::Duration calculate_age (HTTP::HeaderMap const & headers, UnixDateTime request_time, UnixDateTime response_time)
299+ AK::Duration calculate_age (HTTP::HeaderMap const & headers, UnixDateTime request_time, UnixDateTime response_time, AK::Duration current_time_offset_for_testing )
298300{
299301 // The term "age_value" denotes the value of the Age header field (Section 5.1), in a form appropriate for arithmetic
300302 // operation; or 0, if not available.
@@ -306,7 +308,7 @@ AK::Duration calculate_age(HTTP::HeaderMap const& headers, UnixDateTime request_
306308 }
307309
308310 // The term "now" means the current value of this implementation's clock (Section 5.6.7 of [HTTP]).
309- auto now = UnixDateTime::now ();
311+ auto now = UnixDateTime::now () + current_time_offset_for_testing ;
310312
311313 // The term "date_value" denotes the value of the Date header field, in a form appropriate for arithmetic operations.
312314 // See Section 6.6.1 of [HTTP] for the definition of the Date header field and for requirements regarding responses
@@ -406,4 +408,16 @@ void update_header_fields(HTTP::HeaderMap& stored_headers, HTTP::HeaderMap const
406408 }
407409}
408410
411+ AK::Duration compute_current_time_offset_for_testing (Optional<DiskCache&> disk_cache, HTTP::HeaderMap const & request_headers)
412+ {
413+ if (disk_cache.has_value () && disk_cache->mode () == DiskCache::Mode::Testing) {
414+ if (auto header = request_headers.get (TEST_CACHE_REQUEST_TIME_OFFSET); header.has_value ()) {
415+ if (auto offset = header->to_number <i64 >(); offset.has_value ())
416+ return AK::Duration::from_seconds (*offset);
417+ }
418+ }
419+
420+ return {};
421+ }
422+
409423}
0 commit comments