mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-28 14:02:51 +00:00
LibWeb/Fetch: Add freshness notion to HTTP::Response
Defined in RFC9111 "HTTP Caching". Co-Authored-By: Andrew Kaster <akaster@serenityos.org>
This commit is contained in:
parent
c05f296014
commit
fcbc6123bb
Notes:
sideshowbarker
2024-07-17 20:22:04 +09:00
Author: https://github.com/LucasChollet
Commit: fcbc6123bb
Pull-request: https://github.com/SerenityOS/serenity/pull/24406
Reviewed-by: https://github.com/ADKaster
Reviewed-by: https://github.com/alimpfard
Reviewed-by: https://github.com/trflynn89 ✅
2 changed files with 113 additions and 0 deletions
|
@ -25,6 +25,7 @@ JS_DEFINE_ALLOCATOR(OpaqueRedirectFilteredResponse);
|
|||
|
||||
Response::Response(JS::NonnullGCPtr<HeaderList> header_list)
|
||||
: m_header_list(header_list)
|
||||
, m_response_time(UnixDateTime::now())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -207,6 +208,106 @@ bool Response::is_cors_cross_origin() const
|
|||
return type() == Type::Opaque || type() == Type::OpaqueRedirect;
|
||||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-fresh-response
|
||||
bool Response::is_fresh() const
|
||||
{
|
||||
// A fresh response is a response whose current age is within its freshness lifetime.
|
||||
return current_age() < freshness_lifetime();
|
||||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-stale-while-revalidate-response
|
||||
bool Response::is_stale_while_revalidate() const
|
||||
{
|
||||
// A stale-while-revalidate response is a response that is not a fresh response and whose current age is within the stale-while-revalidate lifetime.
|
||||
return !is_fresh() && current_age() < stale_while_revalidate_lifetime();
|
||||
}
|
||||
|
||||
// https://fetch.spec.whatwg.org/#concept-stale-response
|
||||
bool Response::is_stale() const
|
||||
{
|
||||
// A stale response is a response that is not a fresh response or a stale-while-revalidate response.
|
||||
return !is_fresh() && !is_stale_while_revalidate();
|
||||
}
|
||||
|
||||
// https://httpwg.org/specs/rfc9111.html#age.calculations
|
||||
u64 Response::current_age() const
|
||||
{
|
||||
// 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.
|
||||
Optional<Duration> age;
|
||||
if (auto const age_header = header_list()->get("Age"sv.bytes()); age_header.has_value()) {
|
||||
if (auto converted_age = StringView { *age_header }.to_number<u64>(); converted_age.has_value())
|
||||
age = Duration::from_seconds(converted_age.value());
|
||||
}
|
||||
|
||||
auto const age_value = age.value_or(Duration::from_seconds(0));
|
||||
|
||||
// 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 without it.
|
||||
// FIXME: Do we have a parser for HTTP-date?
|
||||
auto const date_value = UnixDateTime::now() - Duration::from_seconds(5);
|
||||
|
||||
// The term "now" means the current value of this implementation's clock (Section 5.6.7 of [HTTP]).
|
||||
auto const now = UnixDateTime::now();
|
||||
|
||||
// The value of the clock at the time of the request that resulted in the stored response.
|
||||
// FIXME: Let's get the correct time.
|
||||
auto const request_time = UnixDateTime::now() - Duration::from_seconds(5);
|
||||
|
||||
// The value of the clock at the time the response was received.
|
||||
auto const response_time = m_response_time;
|
||||
|
||||
auto const apparent_age = max(0, (response_time - date_value).to_seconds());
|
||||
|
||||
auto const response_delay = response_time - request_time;
|
||||
auto const corrected_age_value = age_value + response_delay;
|
||||
|
||||
auto const corrected_initial_age = max(apparent_age, corrected_age_value.to_seconds());
|
||||
|
||||
auto const resident_time = (now - response_time).to_seconds();
|
||||
return corrected_initial_age + resident_time;
|
||||
}
|
||||
|
||||
// https://httpwg.org/specs/rfc9111.html#calculating.freshness.lifetime
|
||||
u64 Response::freshness_lifetime() const
|
||||
{
|
||||
auto const elem = header_list()->get_decode_and_split("Cache-Control"sv.bytes());
|
||||
if (!elem.has_value())
|
||||
return 0;
|
||||
|
||||
// FIXME: If the cache is shared and the s-maxage response directive (Section 5.2.2.10) is present, use its value
|
||||
|
||||
// If the max-age response directive (Section 5.2.2.1) is present, use its value, or
|
||||
for (auto const& directive : *elem) {
|
||||
if (directive.starts_with_bytes("max-age"sv)) {
|
||||
auto equal_offset = directive.find_byte_offset('=').value();
|
||||
auto const value = directive.bytes_as_string_view().substring_view(equal_offset);
|
||||
return value.to_number<u64>().value();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: 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
|
||||
// FIXME: Otherwise, no explicit expiration time is present in the response. A heuristic freshness lifetime might be applicable; see Section 4.2.2.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// https://httpwg.org/specs/rfc5861.html#n-the-stale-while-revalidate-cache-control-extension
|
||||
u64 Response::stale_while_revalidate_lifetime() const
|
||||
{
|
||||
auto const elem = header_list()->get_decode_and_split("Cache-Control"sv.bytes());
|
||||
if (!elem.has_value())
|
||||
return 0;
|
||||
|
||||
for (auto const& directive : *elem) {
|
||||
if (directive.starts_with_bytes("stale-while-revalidate"sv)) {
|
||||
auto equal_offset = directive.find_byte_offset('=').value();
|
||||
auto const value = directive.bytes_as_string_view().substring_view(equal_offset);
|
||||
return value.to_number<u64>().value();
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Non-standard
|
||||
Optional<StringView> Response::network_error_message() const
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue