From 29169149db7f35b93813a2a17a0e850dee6e4185 Mon Sep 17 00:00:00 2001 From: Rene Schallner Date: Sun, 15 Jan 2023 01:23:04 +0100 Subject: [PATCH] endpoints example: better web i/f --- examples/endpoints/endpoints.zig | 64 +++++++++++++- examples/endpoints/html/index.html | 134 ++++++++++++++++++++++++----- examples/endpoints/users.zig | 35 +++++--- 3 files changed, 197 insertions(+), 36 deletions(-) diff --git a/examples/endpoints/endpoints.zig b/examples/endpoints/endpoints.zig index cc364e3..961faeb 100644 --- a/examples/endpoints/endpoints.zig +++ b/examples/endpoints/endpoints.zig @@ -23,8 +23,8 @@ pub fn init( .path = user_path, .get = getUser, .post = postUser, - .put = null, - .delete = null, + .put = putUser, + .delete = deleteUser, }); list_endpoint = zap.SimpleEndpoint.init(.{ .path = userlist_path, @@ -107,3 +107,63 @@ fn postUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { } } } + +fn putUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { + _ = e; + if (r.path) |path| { + if (userIdFromPath(path)) |id| { + if (users.get(id)) |_| { + if (r.body) |body| { + var stream = std.json.TokenStream.init(body); + var maybe_user: ?User = std.json.parse( + User, + &stream, + .{ .allocator = alloc }, + ) catch null; + if (maybe_user) |u| { + defer std.json.parseFree( + User, + u, + .{ .allocator = alloc }, + ); + if (users.update(id, u.first_name, u.last_name)) { + if (zap.stringify(.{ + .status = "OK", + .id = id, + }, .{})) |json| { + _ = r.sendJson(json); + } + } else { + if (zap.stringify(.{ + .status = "ERROR", + .id = id, + }, .{})) |json| { + _ = r.sendJson(json); + } + } + } + } + } + } + } +} + +fn deleteUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { + _ = e; + if (r.path) |path| { + if (userIdFromPath(path)) |id| { + if (users.delete(id)) { + if (zap.stringify(.{ .status = "OK", .id = id }, .{})) |json| { + _ = r.sendJson(json); + } + } else { + if (zap.stringify(.{ + .status = "ERROR", + .id = id, + }, .{})) |json| { + _ = r.sendJson(json); + } + } + } + } +} diff --git a/examples/endpoints/html/index.html b/examples/endpoints/html/index.html index 2379773..c90eb61 100644 --- a/examples/endpoints/html/index.html +++ b/examples/endpoints/html/index.html @@ -23,6 +23,18 @@ border: 2px solid #cdb4db; padding: 15px; margin-top: 10px; + width: 80%; + height: 18rem; + } + form { + border: 2px solid #cdb4db; + border-radius: 12px; + padding: 15px; + margin-top: 10px; + font-size: 1em; + width: 80%; + text-align: center; + justify-content: center; } button { background-color: #ffafcc; @@ -37,32 +49,46 @@ display: flex; justify-content: center; } + table { + background-color:#181818; + } + th { + color: #B06060; + padding: 15px; + } + td { + color: #B0B0B0; + }
-

Show example user 1

-

Show example user 2

-

Show ALL users

+
+
+
+ +
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+

Show JSON for all users

-
-
-
- -
-
-
- -
-
- -
-
(hide)
- +
diff --git a/examples/endpoints/users.zig b/examples/endpoints/users.zig index 788a0b5..d121da0 100644 --- a/examples/endpoints/users.zig +++ b/examples/endpoints/users.zig @@ -2,6 +2,7 @@ const std = @import("std"); alloc: std.mem.Allocator = undefined, users: std.AutoHashMap(usize, InternalUser) = undefined, +count: usize = 0, pub const Self = @This(); @@ -14,6 +15,7 @@ const InternalUser = struct { }; pub const User = struct { + id: usize = 0, first_name: []const u8, last_name: []const u8, }; @@ -28,9 +30,12 @@ pub fn init(a: std.mem.Allocator) Self { /// the request will be freed (and reused by facilio) when it's /// completed, so we take copies of the names pub fn addByName(self: *Self, first: ?[]const u8, last: ?[]const u8) !usize { - var created = try self.alloc.alloc(InternalUser, 1); - var user = created[0]; - user.id = self.users.count() + 1; + // TODO: get rid of the temp allocation here + var temp = try self.alloc.alloc(InternalUser, 1); + defer self.alloc.free(temp); + var user = temp[0]; + self.count = self.count + 1; + user.id = self.count; user.firstnamelen = 0; user.lastnamelen = 0; if (first) |firstname| { @@ -46,16 +51,13 @@ pub fn addByName(self: *Self, first: ?[]const u8, last: ?[]const u8) !usize { } pub fn delete(self: *Self, id: usize) bool { - if (self.users.get(id)) |pUser| { - self.alloc.free(pUser); - return self.users.remove(id); - } - return false; + return self.users.remove(id); } pub fn get(self: *Self, id: usize) ?User { if (self.users.get(id)) |pUser| { return .{ + .id = pUser.id, .first_name = pUser.firstnamebuf[0..pUser.firstnamelen], .last_name = pUser.lastnamebuf[0..pUser.lastnamelen], }; @@ -63,16 +65,22 @@ pub fn get(self: *Self, id: usize) ?User { return null; } -pub fn update(self: *Self, id: usize, first: ?[]const u8, last: ?[]const u8) bool { - if (self.users.get(id)) |pUser| { - pUser.firstnamelen = 0; - pUser.lastnamelen = 0; +pub fn update( + self: *Self, + id: usize, + first: ?[]const u8, + last: ?[]const u8, +) bool { + var user: ?InternalUser = self.users.get(id); + if (user) |*pUser| { + pUser.*.firstnamelen = 0; + pUser.*.lastnamelen = 0; if (first) |firstname| { std.mem.copy(u8, pUser.firstnamebuf[0..], firstname); pUser.firstnamelen = firstname.len; } if (last) |lastname| { - std.mem.copy(u8, pUser.lastname[0..], lastname); + std.mem.copy(u8, pUser.lastnamebuf[0..], lastname); pUser.lastnamelen = lastname.len; } return true; @@ -104,6 +112,7 @@ const JsonUserIterator = struct { pub fn next(this: *This) ?User { if (this.it.next()) |pUser| { return User{ + .id = pUser.id, .first_name = pUser.firstnamebuf[0..pUser.firstnamelen], .last_name = pUser.lastnamebuf[0..pUser.lastnamelen], };