mirror of
https://github.com/zigzap/zap.git
synced 2025-10-20 15:14:08 +00:00
fixed AuthEndpoint callbacks, BasicAuth logging
AuthEndpoint callbacks now provide pointers to the original SimpleEndpoint structs, so their fieldParentPtr calls work. Added extensive debug() logging to BasicAuth with .UserPassword.
This commit is contained in:
parent
828dc16668
commit
d0c59ab008
6 changed files with 90 additions and 12 deletions
|
@ -47,6 +47,7 @@ pub fn build(b: *std.build.Builder) !void {
|
||||||
.{ .name = "hello_json", .src = "examples/hello_json/hello_json.zig" },
|
.{ .name = "hello_json", .src = "examples/hello_json/hello_json.zig" },
|
||||||
.{ .name = "endpoint", .src = "examples/endpoint/main.zig" },
|
.{ .name = "endpoint", .src = "examples/endpoint/main.zig" },
|
||||||
.{ .name = "wrk", .src = "wrk/zig/main.zig" },
|
.{ .name = "wrk", .src = "wrk/zig/main.zig" },
|
||||||
|
.{ .name = "wrk_zigstd", .src = "wrk/zigstd/main.zig" },
|
||||||
.{ .name = "mustache", .src = "examples/mustache/mustache.zig" },
|
.{ .name = "mustache", .src = "examples/mustache/mustache.zig" },
|
||||||
.{ .name = "endpoint_auth", .src = "examples/endpoint_auth/endpoint_auth.zig" },
|
.{ .name = "endpoint_auth", .src = "examples/endpoint_auth/endpoint_auth.zig" },
|
||||||
}) |excfg| {
|
}) |excfg| {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
.{
|
.{
|
||||||
.name = "zap",
|
.name = "zap",
|
||||||
.version = "0.0.11",
|
.version = "0.0.13",
|
||||||
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.@"facil.io" = .{
|
.@"facil.io" = .{
|
||||||
|
|
|
@ -91,7 +91,7 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type {
|
||||||
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
|
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
|
||||||
if (authEp.authenticator.authenticateRequest(&r) == false) {
|
if (authEp.authenticator.authenticateRequest(&r) == false) {
|
||||||
if (e.settings.unauthorized) |foo| {
|
if (e.settings.unauthorized) |foo| {
|
||||||
foo(e, r);
|
foo(authEp.endpoint, r);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
r.setStatus(.unauthorized);
|
r.setStatus(.unauthorized);
|
||||||
|
@ -100,7 +100,7 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// auth successful
|
// auth successful
|
||||||
authEp.endpoint.settings.get.?(e, r);
|
authEp.endpoint.settings.get.?(authEp.endpoint, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// here, the auth_endpoint will be passed in
|
/// here, the auth_endpoint will be passed in
|
||||||
|
@ -108,7 +108,7 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type {
|
||||||
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
|
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
|
||||||
if (authEp.authenticator.authenticateRequest(&r) == false) {
|
if (authEp.authenticator.authenticateRequest(&r) == false) {
|
||||||
if (e.settings.unauthorized) |foo| {
|
if (e.settings.unauthorized) |foo| {
|
||||||
foo(e, r);
|
foo(authEp.endpoint, r);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
r.setStatus(.unauthorized);
|
r.setStatus(.unauthorized);
|
||||||
|
@ -117,7 +117,7 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// auth successful
|
// auth successful
|
||||||
authEp.endpoint.settings.post.?(e, r);
|
authEp.endpoint.settings.post.?(authEp.endpoint, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// here, the auth_endpoint will be passed in
|
/// here, the auth_endpoint will be passed in
|
||||||
|
@ -125,7 +125,7 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type {
|
||||||
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
|
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
|
||||||
if (authEp.authenticator.authenticateRequest(&r) == false) {
|
if (authEp.authenticator.authenticateRequest(&r) == false) {
|
||||||
if (e.settings.unauthorized) |foo| {
|
if (e.settings.unauthorized) |foo| {
|
||||||
foo(e, r);
|
foo(authEp.endpoint, r);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
r.setStatus(.unauthorized);
|
r.setStatus(.unauthorized);
|
||||||
|
@ -134,7 +134,7 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// auth successful
|
// auth successful
|
||||||
authEp.endpoint.settings.put.?(e, r);
|
authEp.endpoint.settings.put.?(authEp.endpoint, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// here, the auth_endpoint will be passed in
|
/// here, the auth_endpoint will be passed in
|
||||||
|
@ -142,7 +142,7 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type {
|
||||||
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
|
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e);
|
||||||
if (authEp.authenticator.authenticateRequest(&r) == false) {
|
if (authEp.authenticator.authenticateRequest(&r) == false) {
|
||||||
if (e.settings.unauthorized) |foo| {
|
if (e.settings.unauthorized) |foo| {
|
||||||
foo(e, r);
|
foo(authEp.endpoint, r);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
r.setStatus(.unauthorized);
|
r.setStatus(.unauthorized);
|
||||||
|
@ -151,7 +151,7 @@ pub fn AuthenticatingEndpoint(comptime Authenticator: type) type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// auth successful
|
// auth successful
|
||||||
authEp.endpoint.settings.delete.?(e, r);
|
authEp.endpoint.settings.delete.?(authEp.endpoint, r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,31 +92,63 @@ pub fn BasicAuth(comptime Lookup: type, comptime kind: BasicAuthStrategy) type {
|
||||||
|
|
||||||
/// Use this to decode the auth_header into user:pass, lookup pass in lookup
|
/// Use this to decode the auth_header into user:pass, lookup pass in lookup
|
||||||
pub fn authenticateUserPass(self: *Self, auth_header: []const u8) bool {
|
pub fn authenticateUserPass(self: *Self, auth_header: []const u8) bool {
|
||||||
|
zap.debug("AuthenticateUserPass\n", .{});
|
||||||
const encoded = auth_header[AuthScheme.Basic.str().len..];
|
const encoded = auth_header[AuthScheme.Basic.str().len..];
|
||||||
const decoder = std.base64.standard.Decoder;
|
const decoder = std.base64.standard.Decoder;
|
||||||
var buffer: [0x100]u8 = undefined;
|
var buffer: [0x100]u8 = undefined;
|
||||||
if (decoder.calcSizeForSlice(encoded)) |decoded_size| {
|
if (decoder.calcSizeForSlice(encoded)) |decoded_size| {
|
||||||
if (decoded_size >= buffer.len) {
|
if (decoded_size >= buffer.len) {
|
||||||
|
zap.debug(
|
||||||
|
"ERROR: UserPassAuth: decoded_size {d} >= buffer.len {d}\n",
|
||||||
|
.{ decoded_size, buffer.len },
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var decoded = buffer[0..decoded_size];
|
var decoded = buffer[0..decoded_size];
|
||||||
decoder.decode(decoded, encoded) catch return false;
|
decoder.decode(decoded, encoded) catch |err| {
|
||||||
|
zap.debug(
|
||||||
|
"ERROR: UserPassAuth: unable to decode `{s}`: {any}\n",
|
||||||
|
.{ encoded, err },
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
// we have decoded
|
// we have decoded
|
||||||
// we can split
|
// we can split
|
||||||
var it = std.mem.split(u8, decoded, ":");
|
var it = std.mem.split(u8, decoded, ":");
|
||||||
const user = it.next();
|
const user = it.next();
|
||||||
const pass = it.next();
|
const pass = it.next();
|
||||||
if (user == null or pass == null) {
|
if (user == null or pass == null) {
|
||||||
|
zap.debug(
|
||||||
|
"ERROR: UserPassAuth: user {any} or pass {any} is null\n",
|
||||||
|
.{ user, pass },
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// now, do the lookup
|
// now, do the lookup
|
||||||
const actual_pw = self.lookup.*.get(user.?);
|
const actual_pw = self.lookup.*.get(user.?);
|
||||||
if (actual_pw) |pw| {
|
if (actual_pw) |pw| {
|
||||||
return std.mem.eql(u8, pass.?, pw);
|
const ret = std.mem.eql(u8, pass.?, pw);
|
||||||
|
zap.debug(
|
||||||
|
"INFO: UserPassAuth for user `{s}`: `{s}` == pass `{s}` = {}\n",
|
||||||
|
.{ user.?, pw, pass.?, ret },
|
||||||
|
);
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
zap.debug(
|
||||||
|
"ERROR: UserPassAuth: user `{s}` not found in map of size {d}!\n",
|
||||||
|
.{ user.?, self.lookup.*.count() },
|
||||||
|
);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} else |_| {
|
} else |err| {
|
||||||
// can't calc slice size --> fallthrough to return false
|
// can't calc slice size --> fallthrough to return false
|
||||||
|
zap.debug(
|
||||||
|
"ERROR: UserPassAuth: cannot calc slize size for encoded `{s}`: {any} \n",
|
||||||
|
.{ encoded, err },
|
||||||
|
);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
zap.debug("UNREACHABLE\n", .{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +160,7 @@ pub fn BasicAuth(comptime Lookup: type, comptime kind: BasicAuthStrategy) type {
|
||||||
|
|
||||||
// dispatch based on kind
|
// dispatch based on kind
|
||||||
pub fn authenticate(self: *Self, auth_header: []const u8) bool {
|
pub fn authenticate(self: *Self, auth_header: []const u8) bool {
|
||||||
|
zap.debug("AUTHENTICATE\n", .{});
|
||||||
// switch (self.kind) {
|
// switch (self.kind) {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
.UserPass => return self.authenticateUserPass(auth_header),
|
.UserPass => return self.authenticateUserPass(auth_header),
|
||||||
|
@ -135,9 +168,12 @@ pub fn BasicAuth(comptime Lookup: type, comptime kind: BasicAuthStrategy) type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn authenticateRequest(self: *Self, r: *const zap.SimpleRequest) bool {
|
pub fn authenticateRequest(self: *Self, r: *const zap.SimpleRequest) bool {
|
||||||
|
zap.debug("AUTHENTICATE REQUEST\n", .{});
|
||||||
if (extractAuthHeader(.Basic, r)) |auth_header| {
|
if (extractAuthHeader(.Basic, r)) |auth_header| {
|
||||||
|
zap.debug("Auth Header found!\n", .{});
|
||||||
return self.authenticate(auth_header);
|
return self.authenticate(auth_header);
|
||||||
}
|
}
|
||||||
|
zap.debug("NO Auth Header found!\n", .{});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -18,6 +18,13 @@ if [ "$SUBJECT" = "zig" ] ; then
|
||||||
URL=http://127.0.0.1:3000
|
URL=http://127.0.0.1:3000
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$SUBJECT" = "zigstd" ] ; then
|
||||||
|
zig build -Doptimize=ReleaseFast wrk_zigstd > /dev/null
|
||||||
|
./zig-out/bin/wrk_zigstd &
|
||||||
|
PID=$!
|
||||||
|
URL=http://127.0.0.1:3000
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$SUBJECT" = "go" ] ; then
|
if [ "$SUBJECT" = "go" ] ; then
|
||||||
cd wrk/go && go build main.go
|
cd wrk/go && go build main.go
|
||||||
./main &
|
./main &
|
||||||
|
|
34
wrk/zigstd/main.zig
Normal file
34
wrk/zigstd/main.zig
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
const allocator = std.heap.page_allocator;
|
||||||
|
var server = std.http.Server.init(allocator, .{
|
||||||
|
.reuse_address = true,
|
||||||
|
});
|
||||||
|
defer server.deinit();
|
||||||
|
const address = try std.net.Address.parseIp("127.0.0.1", 3000);
|
||||||
|
try server.listen(address);
|
||||||
|
const max_header_size = 8192;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
var res = try server.accept(.{ .dynamic = max_header_size });
|
||||||
|
const start_time = std.time.nanoTimestamp();
|
||||||
|
defer res.deinit();
|
||||||
|
defer res.reset();
|
||||||
|
try res.wait();
|
||||||
|
|
||||||
|
const server_body: []const u8 = "HI FROM ZIG STD!\n";
|
||||||
|
res.transfer_encoding = .{ .content_length = server_body.len };
|
||||||
|
try res.headers.append("content-type", "text/plain");
|
||||||
|
try res.headers.append("connection", "close");
|
||||||
|
try res.do();
|
||||||
|
|
||||||
|
var buf: [128]u8 = undefined;
|
||||||
|
_ = try res.readAll(&buf);
|
||||||
|
_ = try res.writer().writeAll(server_body);
|
||||||
|
try res.finish();
|
||||||
|
const end_time = std.time.nanoTimestamp();
|
||||||
|
const diff = end_time - start_time;
|
||||||
|
std.debug.print("{d}\n", .{diff});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue