Files
ladybird/Libraries/LibHTTP/Cache/Utilities.h
Timothy Flynn d97a3d9b5a LibHTTP+RequestServer: Send revalidation attributes without parsing
The caching RFC is quite strict about the format of date strings. If we
received a revalidation attribute with an invalid date string, we would
previously fail a runtime assertion. This was because to start a
revalidation request, we would simply check for the presence of any
revalidation header; but then when we issued the request, we would fail
to parse the header, and end up with all attributes being null.

We now don't parse the revalidation attributes at all. Whatever we
receive in the Last-Modified response header is what we will send in the
If-Modified-Since request header, verbatim. For better or worse, this is
how other browsers behave. So if the server sends us an invalid date
string, it can receive its own date format for revalidation.
2026-02-10 09:09:53 -05:00

64 lines
2.6 KiB
C++

/*
* Copyright (c) 2025-2026, Tim Flynn <trflynn89@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/LexicalPath.h>
#include <AK/StringView.h>
#include <AK/Time.h>
#include <AK/Types.h>
#include <LibHTTP/Forward.h>
#include <LibHTTP/HeaderList.h>
#include <LibURL/Forward.h>
namespace HTTP {
constexpr inline auto TEST_CACHE_ENABLED_HEADER = "X-Ladybird-Enable-Disk-Cache"sv;
constexpr inline auto TEST_CACHE_STATUS_HEADER = "X-Ladybird-Disk-Cache-Status"sv;
constexpr inline auto TEST_CACHE_REVALIDATION_STATUS_HEADER = "X-Ladybird-Revalidation-Status"sv;
constexpr inline auto TEST_CACHE_REQUEST_TIME_OFFSET = "X-Ladybird-Request-Time-Offset"sv;
String serialize_url_for_cache_storage(URL::URL const&);
u64 create_cache_key(StringView url, StringView method);
u64 create_vary_key(HeaderList const& request_headers, HeaderList const& response_headers);
LexicalPath path_for_cache_entry(LexicalPath const& cache_directory, u64 cache_key, u64 vary_key);
bool is_cacheable(StringView method, HeaderList const&);
bool is_cacheable(u32 status_code, HeaderList const&);
bool is_header_exempted_from_storage(StringView name);
AK::Duration calculate_freshness_lifetime(u32 status_code, HeaderList const&, AK::Duration current_time_offset_for_testing = {});
AK::Duration calculate_age(HeaderList const&, UnixDateTime request_time, UnixDateTime response_time, AK::Duration current_time_offset_for_testing = {});
AK::Duration calculate_stale_while_revalidate_lifetime(HeaderList const&, AK::Duration freshness_lifetime);
enum class CacheLifetimeStatus {
Fresh,
Expired,
MustRevalidate,
StaleWhileRevalidate,
};
CacheLifetimeStatus cache_lifetime_status(HeaderList const& request_headers, HeaderList const& response_headers, AK::Duration freshness_lifetime, AK::Duration current_age);
struct RevalidationAttributes {
static RevalidationAttributes create(HeaderList const&);
Optional<ByteString> etag;
Optional<ByteString> last_modified;
};
void store_header_and_trailer_fields(HeaderList&, HeaderList const&);
void update_header_fields(HeaderList&, HeaderList const&);
bool contains_cache_control_directive(StringView cache_control, StringView directive);
Optional<StringView> extract_cache_control_directive(StringView cache_control, StringView directive);
Optional<AK::Duration> extract_cache_control_duration_directive(StringView cache_control, StringView directive, Optional<AK::Duration> valueless_fallback = {});
ByteString normalize_request_vary_header_values(StringView header, HeaderList const& request_headers);
AK::Duration compute_current_time_offset_for_testing(Optional<DiskCache&>, HeaderList const& request_headers);
}