milestone 10: doh and dot listeners, cert store with hot reload and cert reload api
This commit is contained in:
@@ -56,6 +56,7 @@ const types = @import("../dns/types.zig");
|
||||
const upstreams_repo = @import("../storage/repositories/upstreams_repo.zig");
|
||||
|
||||
const handlers_blocklists = @import("handlers/blocklists.zig");
|
||||
const handlers_certs = @import("handlers/certs.zig");
|
||||
const handlers_health = @import("handlers/health.zig");
|
||||
const handlers_live = @import("handlers/live.zig");
|
||||
const handlers_lookup = @import("handlers/lookup.zig");
|
||||
@@ -670,6 +671,11 @@ const contract = [_]Contract{
|
||||
.{ .method = .GET, .pattern = "/api/settings", .auth = .session, .target = "/api/settings", .status = 200, .check = jsonShape(SettingsView) },
|
||||
.{ .method = .PUT, .pattern = "/api/settings", .auth = .session, .target = "/api/settings", .body = "{\"dns\":{\"port\":5353}}", .status = 200, .check = jsonShape(SettingsView) },
|
||||
|
||||
// Certificates. The walk's environment wires no cert store, so both
|
||||
// endpoints report disabled — and the reload still answers 200 (m10
|
||||
// ruling 8: the outcome is the payload).
|
||||
.{ .method = .POST, .pattern = "/api/certs/reload", .auth = .session, .target = "/api/certs/reload", .status = 200, .check = jsonShape(handlers_certs.View) },
|
||||
|
||||
// The walk's last delete returns the groups table to its seeded shape.
|
||||
.{ .method = .DELETE, .pattern = "/api/groups/{id}", .auth = .session, .target = "/api/groups/2", .status = 204, .kind = .none },
|
||||
};
|
||||
@@ -773,6 +779,36 @@ test "W10 contract: every route answers its documented status and shape" {
|
||||
try bounded(env.io(), default_budget, contractWalk, .{ env.io(), env });
|
||||
}
|
||||
|
||||
// The wire shape of the certs reload payload, restated so the handler's own
|
||||
// `View` cannot vouch for itself. Runs in every suite: it needs no socket.
|
||||
const CertOutcomeShape = struct { enabled: bool, reloaded: bool, @"error": ?[]const u8 };
|
||||
const CertsReloadShape = struct { doh: CertOutcomeShape, dot: CertOutcomeShape };
|
||||
|
||||
test "the certs reload payload with both endpoints disabled parses strictly" {
|
||||
const gpa = testing.allocator;
|
||||
|
||||
var state: server.WebState = .{ .gpa = gpa };
|
||||
const view = handlers_certs.applyReload(&state, undefined);
|
||||
|
||||
var out: std.Io.Writer.Allocating = .init(gpa);
|
||||
defer out.deinit();
|
||||
try std.json.Stringify.value(view, .{}, &out.writer);
|
||||
|
||||
var arena_state: std.heap.ArenaAllocator = .init(gpa);
|
||||
defer arena_state.deinit();
|
||||
const parsed = try std.json.parseFromSliceLeaky(
|
||||
CertsReloadShape,
|
||||
arena_state.allocator(),
|
||||
out.written(),
|
||||
.{ .ignore_unknown_fields = false },
|
||||
);
|
||||
for ([_]CertOutcomeShape{ parsed.doh, parsed.dot }) |per_endpoint| {
|
||||
try testing.expect(!per_endpoint.enabled);
|
||||
try testing.expect(!per_endpoint.reloaded);
|
||||
try testing.expectEqual(@as(?[]const u8, null), per_endpoint.@"error");
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// auth on/off matrix (rulings 17, 18)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user