Skip to content

Commit

Permalink
handler- send the Etag header for better page caching
Browse files Browse the repository at this point in the history
  • Loading branch information
nektro committed Feb 4, 2022
1 parent 5ad614c commit 5f08e0c
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/handler/_handler.zig
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ fn file_route(comptime path: string) http.router.Route {
try response.headers.put("Content-Type", mediatype);
}
const w = response.writer();
try response.headers.put("Etag", try etag(request.arena, @field(files, path)));
try w.writeAll(@field(files, path));
}
};
Expand Down Expand Up @@ -132,3 +133,9 @@ pub fn logout(_: void, response: *http.Response, request: http.Request, args: st
try cookies.delete(response, "jwt");
try _internal.redirectTo(response, "./");
}

fn etag(alloc: std.mem.Allocator, input: string) !string {
var h = std.hash.Wyhash.init(0);
h.update(input);
return try std.fmt.allocPrint(alloc, "{x}", .{h.final()});
}
62 changes: 62 additions & 0 deletions src/handler/_internal.zig
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,32 @@ pub fn writePageResponse(alloc: std.mem.Allocator, response: *http.Response, req
_ = request;
try response.headers.put("Content-Type", "text/html");

var h = std.hash.Wyhash.init(0);
h.update(@field(files, name));
inline for (std.meta.fields(@TypeOf(data))) |field| {
hashUp(&h, @field(data, field.name));
}
try response.headers.put("Etag", try std.fmt.allocPrint(alloc, "\"{x}\"", .{h.final()}));

const w = response.writer();
const head = files.@"/_header.pek";
const page = @field(files, name);
const tmpl = comptime pek.parse(head ++ page);
try pek.compile(root, alloc, w, tmpl, data);
}

const wyhash = struct {
pub const Writer = std.io.Writer(*std.hash.Wyhash, error{}, write);

fn write(self: *std.hash.Wyhash, b: []const u8) error{}!usize {
self.update(b);
}

pub fn writer(self: *std.hash.Wyhash) Writer {
return .{ .context = self };
}
};

pub const JWT = struct {
const Payload = struct {
iss: string, // issuer
Expand Down Expand Up @@ -209,3 +228,46 @@ pub fn readFileContents(dir: std.fs.Dir, alloc: std.mem.Allocator, path: string)
defer file.close();
return try file.reader().readAllAlloc(alloc, 1024 * 1024 * 2); // 2mb
}

pub fn hashUp(h: *std.hash.Wyhash, item: anytype) void {
if (comptime std.meta.trait.isZigString(@TypeOf(item))) {
h.update(item);
return;
}
switch (@TypeOf(item)) {
db.Remote => h.update(item.domain),
db.Remote.Repo, db.User, db.Package, db.Version => hashUp(h, item.id),
u64 => h.update(&std.mem.toBytes(item)),
bool => h.update(if (item) "true" else "false"),

[]const db.User,
[]const db.Package,
[]const db.Version,
[]const db.Remote.Repo,
[]const db.CountStat,
[]const db.TimeStat,
=> {
h.update("[");
defer h.update("]");
for (item) |inner| {
hashUp(h, inner);
}
},

?db.User => {
h.update(if (item) |_| "1" else "0");
},

db.CountStat => {
h.update(item.ulid);
hashUp(h, item.count);
},

db.TimeStat => {
h.update(item.ulid);
h.update(item.time);
},

else => |t| @compileError(@typeName(t)),
}
}

0 comments on commit 5f08e0c

Please sign in to comment.