mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-12-08 06:09:58 +00:00
RequestServer: Add a hook to advance a request's clock time for testing
For example, we will want to be able to test that a cached object was expired after N seconds. Rather than waiting that time during testing, this adds a testing-only request header to internally advance the clock for a single HTTP request.
This commit is contained in:
parent
b2c112c41a
commit
4de3f77d37
Notes:
github-actions[bot]
2025-11-20 08:35:34 +00:00
Author: https://github.com/trflynn89
Commit: 4de3f77d37
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6861
Reviewed-by: https://github.com/gmta ✅
7 changed files with 50 additions and 22 deletions
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <LibCrypto/Hash/SHA1.h>
|
||||
#include <LibURL/URL.h>
|
||||
#include <RequestServer/Cache/DiskCache.h>
|
||||
#include <RequestServer/Cache/Utilities.h>
|
||||
|
||||
namespace RequestServer {
|
||||
|
|
@ -207,11 +208,12 @@ bool is_header_exempted_from_storage(StringView name)
|
|||
|
||||
// AD-HOC: Exclude headers used only for testing.
|
||||
TEST_CACHE_ENABLED_HEADER,
|
||||
TEST_CACHE_STATUS_HEADER);
|
||||
TEST_CACHE_STATUS_HEADER,
|
||||
TEST_CACHE_REQUEST_TIME_OFFSET);
|
||||
}
|
||||
|
||||
// https://httpwg.org/specs/rfc9111.html#heuristic.freshness
|
||||
static AK::Duration calculate_heuristic_freshness_lifetime(HTTP::HeaderMap const& headers)
|
||||
static AK::Duration calculate_heuristic_freshness_lifetime(HTTP::HeaderMap const& headers, AK::Duration current_time_offset_for_testing)
|
||||
{
|
||||
// Since origin servers do not always provide explicit expiration times, a cache MAY assign a heuristic expiration
|
||||
// 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
|
|||
if (!last_modified.has_value())
|
||||
return {};
|
||||
|
||||
auto now = UnixDateTime::now();
|
||||
auto now = UnixDateTime::now() + current_time_offset_for_testing;
|
||||
auto since_last_modified = now - *last_modified;
|
||||
auto seconds = since_last_modified.to_seconds();
|
||||
|
||||
|
|
@ -243,7 +245,7 @@ static AK::Duration calculate_heuristic_freshness_lifetime(HTTP::HeaderMap const
|
|||
}
|
||||
|
||||
// https://httpwg.org/specs/rfc9111.html#calculating.freshness.lifetime
|
||||
AK::Duration calculate_freshness_lifetime(u32 status_code, HTTP::HeaderMap const& headers)
|
||||
AK::Duration calculate_freshness_lifetime(u32 status_code, HTTP::HeaderMap const& headers, AK::Duration current_time_offset_for_testing)
|
||||
{
|
||||
// A cache can calculate the freshness lifetime (denoted as freshness_lifetime) of a response by evaluating the
|
||||
// following rules and using the first match:
|
||||
|
|
@ -265,8 +267,8 @@ AK::Duration calculate_freshness_lifetime(u32 status_code, HTTP::HeaderMap const
|
|||
// * If the Expires response header field (Section 5.3) is present, use its value minus the value of the Date response
|
||||
// header field (using the time the message was received if it is not present, as per Section 6.6.1 of [HTTP]), or
|
||||
if (auto expires = parse_http_date(headers.get("Expires"sv)); expires.has_value()) {
|
||||
auto date = parse_http_date(headers.get("Date"sv)).value_or_lazy_evaluated([]() {
|
||||
return UnixDateTime::now();
|
||||
auto date = parse_http_date(headers.get("Date"sv)).value_or_lazy_evaluated([&]() {
|
||||
return UnixDateTime::now() + current_time_offset_for_testing;
|
||||
});
|
||||
|
||||
return *expires - date;
|
||||
|
|
@ -287,14 +289,14 @@ AK::Duration calculate_freshness_lifetime(u32 status_code, HTTP::HeaderMap const
|
|||
}
|
||||
|
||||
if (heuristics_allowed)
|
||||
return calculate_heuristic_freshness_lifetime(headers);
|
||||
return calculate_heuristic_freshness_lifetime(headers, current_time_offset_for_testing);
|
||||
|
||||
// No explicit expiration time, and heuristics not allowed or not applicable.
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://httpwg.org/specs/rfc9111.html#age.calculations
|
||||
AK::Duration calculate_age(HTTP::HeaderMap const& headers, UnixDateTime request_time, UnixDateTime response_time)
|
||||
AK::Duration calculate_age(HTTP::HeaderMap const& headers, UnixDateTime request_time, UnixDateTime response_time, AK::Duration current_time_offset_for_testing)
|
||||
{
|
||||
// The term "age_value" denotes the value of the Age header field (Section 5.1), in a form appropriate for arithmetic
|
||||
// operation; or 0, if not available.
|
||||
|
|
@ -306,7 +308,7 @@ AK::Duration calculate_age(HTTP::HeaderMap const& headers, UnixDateTime request_
|
|||
}
|
||||
|
||||
// The term "now" means the current value of this implementation's clock (Section 5.6.7 of [HTTP]).
|
||||
auto now = UnixDateTime::now();
|
||||
auto now = UnixDateTime::now() + current_time_offset_for_testing;
|
||||
|
||||
// The term "date_value" denotes the value of the Date header field, in a form appropriate for arithmetic operations.
|
||||
// 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
|
|||
}
|
||||
}
|
||||
|
||||
AK::Duration compute_current_time_offset_for_testing(Optional<DiskCache&> disk_cache, HTTP::HeaderMap const& request_headers)
|
||||
{
|
||||
if (disk_cache.has_value() && disk_cache->mode() == DiskCache::Mode::Testing) {
|
||||
if (auto header = request_headers.get(TEST_CACHE_REQUEST_TIME_OFFSET); header.has_value()) {
|
||||
if (auto offset = header->to_number<i64>(); offset.has_value())
|
||||
return AK::Duration::from_seconds(*offset);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue