mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-03-21 20:24:42 +00:00
use CacheControl and Vary
This commit is contained in:
33
src/network/cache/Cache.zig
vendored
33
src/network/cache/Cache.zig
vendored
@@ -81,6 +81,13 @@ pub const Vary = union(enum) {
|
|||||||
return .{ .value = value };
|
return .{ .value = value };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: Vary, allocator: std.mem.Allocator) void {
|
||||||
|
switch (self) {
|
||||||
|
.wildcard => {},
|
||||||
|
.value => |v| allocator.free(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toString(self: Vary) []const u8 {
|
pub fn toString(self: Vary) []const u8 {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
.wildcard => "*",
|
.wildcard => "*",
|
||||||
@@ -96,19 +103,14 @@ pub const CachedMetadata = struct {
|
|||||||
status: u16,
|
status: u16,
|
||||||
stored_at: i64,
|
stored_at: i64,
|
||||||
age_at_store: u64,
|
age_at_store: u64,
|
||||||
max_age: u64,
|
|
||||||
|
|
||||||
// for If-None-Match
|
// for If-None-Match
|
||||||
etag: ?[]const u8,
|
etag: ?[]const u8,
|
||||||
// for If-Modified-Since
|
// for If-Modified-Since
|
||||||
last_modified: ?[]const u8,
|
last_modified: ?[]const u8,
|
||||||
// If non-null, must be incorporated into cache key.
|
|
||||||
vary: ?[]const u8,
|
|
||||||
|
|
||||||
must_revalidate: bool,
|
|
||||||
no_cache: bool,
|
|
||||||
immutable: bool,
|
|
||||||
|
|
||||||
|
cache_control: CacheControl,
|
||||||
|
vary: ?Vary,
|
||||||
headers: []const Http.Header,
|
headers: []const Http.Header,
|
||||||
|
|
||||||
pub fn fromHeaders(
|
pub fn fromHeaders(
|
||||||
@@ -143,7 +145,7 @@ pub const CachedMetadata = struct {
|
|||||||
// return null for uncacheable responses
|
// return null for uncacheable responses
|
||||||
if (cc.no_store) return null;
|
if (cc.no_store) return null;
|
||||||
if (vary) |v| if (v == .wildcard) return null;
|
if (vary) |v| if (v == .wildcard) return null;
|
||||||
const resolved_max_age = cc.max_age orelse return null;
|
if (cc.max_age == null) return null;
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.url = url,
|
.url = url,
|
||||||
@@ -151,13 +153,10 @@ pub const CachedMetadata = struct {
|
|||||||
.status = status,
|
.status = status,
|
||||||
.stored_at = timestamp,
|
.stored_at = timestamp,
|
||||||
.age_at_store = age_at_store,
|
.age_at_store = age_at_store,
|
||||||
.max_age = resolved_max_age,
|
|
||||||
.etag = etag,
|
.etag = etag,
|
||||||
.last_modified = last_modified,
|
.last_modified = last_modified,
|
||||||
.must_revalidate = cc.must_revalidate,
|
.cache_control = cc,
|
||||||
.no_cache = cc.no_cache,
|
.vary = vary,
|
||||||
.immutable = cc.immutable,
|
|
||||||
.vary = if (vary) |v| v.toString() else null,
|
|
||||||
.headers = headers,
|
.headers = headers,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -170,15 +169,9 @@ pub const CachedMetadata = struct {
|
|||||||
allocator.free(header.value);
|
allocator.free(header.value);
|
||||||
}
|
}
|
||||||
allocator.free(self.headers);
|
allocator.free(self.headers);
|
||||||
|
if (self.vary) |v| v.deinit(allocator);
|
||||||
if (self.etag) |e| allocator.free(e);
|
if (self.etag) |e| allocator.free(e);
|
||||||
if (self.last_modified) |lm| allocator.free(lm);
|
if (self.last_modified) |lm| allocator.free(lm);
|
||||||
if (self.vary) |v| allocator.free(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn isAgeStale(self: *const CachedMetadata) bool {
|
|
||||||
const now = std.time.timestamp();
|
|
||||||
const age = now - self.stored_at + @as(i64, @intCast(self.age_at_store));
|
|
||||||
return age < @as(i64, @intCast(self.max_age));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
84
src/network/cache/FsCache.zig
vendored
84
src/network/cache/FsCache.zig
vendored
@@ -59,25 +59,35 @@ fn hashKey(key: []const u8) [HASHED_KEY_LEN]u8 {
|
|||||||
|
|
||||||
fn serializeMeta(writer: *std.Io.Writer, meta: *const CachedMetadata) !void {
|
fn serializeMeta(writer: *std.Io.Writer, meta: *const CachedMetadata) !void {
|
||||||
try writer.print("{s}\n{s}\n", .{ meta.url, meta.content_type });
|
try writer.print("{s}\n{s}\n", .{ meta.url, meta.content_type });
|
||||||
try writer.print("{d}\n{d}\n{d}\n{d}\n", .{
|
try writer.print("{d}\n{d}\n{d}\n", .{
|
||||||
meta.status,
|
meta.status,
|
||||||
meta.stored_at,
|
meta.stored_at,
|
||||||
meta.age_at_store,
|
meta.age_at_store,
|
||||||
meta.max_age,
|
|
||||||
});
|
});
|
||||||
try writer.print("{s}\n", .{meta.etag orelse "null"});
|
try writer.print("{s}\n", .{meta.etag orelse "null"});
|
||||||
try writer.print("{s}\n", .{meta.last_modified orelse "null"});
|
try writer.print("{s}\n", .{meta.last_modified orelse "null"});
|
||||||
try writer.print("{s}\n", .{meta.vary orelse "null"});
|
|
||||||
try writer.print("{}\n{}\n{}\n", .{
|
// cache-control
|
||||||
meta.must_revalidate,
|
try writer.print("{d}\n", .{meta.cache_control.max_age orelse 0});
|
||||||
meta.no_cache,
|
try writer.print("{}\n{}\n{}\n{}\n", .{
|
||||||
meta.immutable,
|
meta.cache_control.max_age != null,
|
||||||
|
meta.cache_control.must_revalidate,
|
||||||
|
meta.cache_control.no_cache,
|
||||||
|
meta.cache_control.immutable,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// vary
|
||||||
|
if (meta.vary) |v| {
|
||||||
|
try writer.print("{s}\n", .{v.toString()});
|
||||||
|
} else {
|
||||||
|
try writer.print("null\n", .{});
|
||||||
|
}
|
||||||
try writer.flush();
|
try writer.flush();
|
||||||
|
|
||||||
try writer.print("{d}\n", .{meta.headers.len});
|
try writer.print("{d}\n", .{meta.headers.len});
|
||||||
for (meta.headers) |hdr| {
|
for (meta.headers) |hdr| {
|
||||||
try writer.print("{s}\n{s}\n", .{ hdr.name, hdr.value });
|
try writer.print("{s}\n{s}\n", .{ hdr.name, hdr.value });
|
||||||
|
try writer.flush();
|
||||||
}
|
}
|
||||||
try writer.flush();
|
try writer.flush();
|
||||||
}
|
}
|
||||||
@@ -121,36 +131,57 @@ fn deserializeMeta(allocator: std.mem.Allocator, file: std.fs.File) !CachedMetad
|
|||||||
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
break :blk std.fmt.parseInt(u64, line, 10) catch return error.Malformed;
|
break :blk std.fmt.parseInt(u64, line, 10) catch return error.Malformed;
|
||||||
};
|
};
|
||||||
const max_age = blk: {
|
|
||||||
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
|
||||||
break :blk std.fmt.parseInt(u64, line, 10) catch return error.Malformed;
|
|
||||||
};
|
|
||||||
|
|
||||||
const etag = blk: {
|
const etag = blk: {
|
||||||
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
break :blk if (std.mem.eql(u8, line, "null")) null else try allocator.dupe(u8, line);
|
break :blk if (std.mem.eql(u8, line, "null")) null else try allocator.dupe(u8, line);
|
||||||
};
|
};
|
||||||
|
errdefer if (etag) |e| allocator.free(e);
|
||||||
|
|
||||||
const last_modified = blk: {
|
const last_modified = blk: {
|
||||||
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
break :blk if (std.mem.eql(u8, line, "null")) null else try allocator.dupe(u8, line);
|
break :blk if (std.mem.eql(u8, line, "null")) null else try allocator.dupe(u8, line);
|
||||||
};
|
};
|
||||||
const vary = blk: {
|
errdefer if (last_modified) |lm| allocator.free(lm);
|
||||||
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
|
||||||
break :blk if (std.mem.eql(u8, line, "null")) null else try allocator.dupe(u8, line);
|
// cache-control
|
||||||
|
const cc = cache_control: {
|
||||||
|
const max_age_val = blk: {
|
||||||
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
|
break :blk std.fmt.parseInt(u64, line, 10) catch return error.Malformed;
|
||||||
|
};
|
||||||
|
const max_age_present = blk: {
|
||||||
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
|
break :blk try deserializeMetaBoolean(line);
|
||||||
|
};
|
||||||
|
const must_revalidate = blk: {
|
||||||
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
|
break :blk try deserializeMetaBoolean(line);
|
||||||
|
};
|
||||||
|
const no_cache = blk: {
|
||||||
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
|
break :blk try deserializeMetaBoolean(line);
|
||||||
|
};
|
||||||
|
const immutable = blk: {
|
||||||
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
|
break :blk try deserializeMetaBoolean(line);
|
||||||
|
};
|
||||||
|
break :cache_control Cache.CacheControl{
|
||||||
|
.max_age = if (max_age_present) max_age_val else null,
|
||||||
|
.must_revalidate = must_revalidate,
|
||||||
|
.no_cache = no_cache,
|
||||||
|
.immutable = immutable,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const must_revalidate = blk: {
|
// vary
|
||||||
|
const vary = blk: {
|
||||||
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
break :blk try deserializeMetaBoolean(line);
|
if (std.mem.eql(u8, line, "null")) break :blk null;
|
||||||
};
|
const duped = try allocator.dupe(u8, line);
|
||||||
const no_cache = blk: {
|
break :blk Cache.Vary.parse(duped);
|
||||||
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
|
||||||
break :blk try deserializeMetaBoolean(line);
|
|
||||||
};
|
|
||||||
const immutable = blk: {
|
|
||||||
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
|
||||||
break :blk try deserializeMetaBoolean(line);
|
|
||||||
};
|
};
|
||||||
|
errdefer if (vary) |v| if (v == .value) allocator.free(v.value);
|
||||||
|
|
||||||
const headers = blk: {
|
const headers = blk: {
|
||||||
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
const line = try reader.takeDelimiter('\n') orelse return error.Malformed;
|
||||||
@@ -184,12 +215,9 @@ fn deserializeMeta(allocator: std.mem.Allocator, file: std.fs.File) !CachedMetad
|
|||||||
.status = status,
|
.status = status,
|
||||||
.stored_at = stored_at,
|
.stored_at = stored_at,
|
||||||
.age_at_store = age_at_store,
|
.age_at_store = age_at_store,
|
||||||
.max_age = max_age,
|
.cache_control = cc,
|
||||||
.etag = etag,
|
.etag = etag,
|
||||||
.last_modified = last_modified,
|
.last_modified = last_modified,
|
||||||
.must_revalidate = must_revalidate,
|
|
||||||
.no_cache = no_cache,
|
|
||||||
.immutable = immutable,
|
|
||||||
.vary = vary,
|
.vary = vary,
|
||||||
.headers = headers,
|
.headers = headers,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user