mirror of
https://github.com/zigzap/zap.git
synced 2025-10-21 07:34:08 +00:00
endpoints example: better web i/f
This commit is contained in:
parent
bc07f3393b
commit
29169149db
3 changed files with 197 additions and 36 deletions
|
@ -23,8 +23,8 @@ pub fn init(
|
||||||
.path = user_path,
|
.path = user_path,
|
||||||
.get = getUser,
|
.get = getUser,
|
||||||
.post = postUser,
|
.post = postUser,
|
||||||
.put = null,
|
.put = putUser,
|
||||||
.delete = null,
|
.delete = deleteUser,
|
||||||
});
|
});
|
||||||
list_endpoint = zap.SimpleEndpoint.init(.{
|
list_endpoint = zap.SimpleEndpoint.init(.{
|
||||||
.path = userlist_path,
|
.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,18 @@
|
||||||
border: 2px solid #cdb4db;
|
border: 2px solid #cdb4db;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
margin-top: 10px;
|
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 {
|
button {
|
||||||
background-color: #ffafcc;
|
background-color: #ffafcc;
|
||||||
|
@ -37,15 +49,21 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
table {
|
||||||
|
background-color:#181818;
|
||||||
|
}
|
||||||
|
th {
|
||||||
|
color: #B06060;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
color: #B0B0B0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<p><a href="/user/1">Show example user 1</a></p>
|
<form >
|
||||||
<p><a href="/user/2">Show example user 2</a></p>
|
|
||||||
<p><a href="/list">Show ALL users</a></p>
|
|
||||||
</div>
|
|
||||||
<form style="text-align:center">
|
|
||||||
<div>
|
<div>
|
||||||
<label>First name:</label><br>
|
<label>First name:</label><br>
|
||||||
<input id="first_name"></input>
|
<input id="first_name"></input>
|
||||||
|
@ -54,15 +72,23 @@
|
||||||
<label>Last name:</label><br>
|
<label>Last name:</label><br>
|
||||||
<input id="last_name"></input>
|
<input id="last_name"></input>
|
||||||
</div>
|
</div>
|
||||||
<div class="center">
|
<div >
|
||||||
<button type="button" onclick="onNewUser();">Add new user!</button>
|
<button type="button" onclick="onNewUser();">Add new user!</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
<table id="usertable">
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="center">
|
||||||
|
<p><a href="/list">Show JSON for all users</a></p>
|
||||||
|
</div>
|
||||||
<div style="padding:20px; margin-top: 1rem;">
|
<div style="padding:20px; margin-top: 1rem;">
|
||||||
<label style="margin-bottom: 10px;">Log Output:</label>
|
<label style="margin-bottom: 10px;">Log Output:</label>
|
||||||
<a id="logtoggler" onclick="toggleLog();" href="#">(hide)</a>
|
<a id="logtoggler" onclick="toggleLog();" href="#">(hide)</a>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<textarea id="log" style="width:80%; height: 18rem; display:block;"></textarea>
|
<textarea id="log"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
|
@ -87,11 +113,11 @@
|
||||||
eL.scrollTop = eL.scrollHeight;
|
eL.scrollTop = eL.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendJSON(data, slug) {
|
function sendJSON(data, slug, method="POST") {
|
||||||
json = JSON.stringify(data);
|
json = JSON.stringify(data);
|
||||||
log("SENDING: " + json);
|
log("SENDING: " + json);
|
||||||
const response = fetch(slug, {
|
const response = fetch(slug, {
|
||||||
method: "POST",
|
method: method,
|
||||||
body: json,
|
body: json,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json; charset=UTF-8"
|
"Content-Type": "application/json; charset=UTF-8"
|
||||||
|
@ -107,14 +133,80 @@
|
||||||
first_name: first_name,
|
first_name: first_name,
|
||||||
last_name: last_name,
|
last_name: last_name,
|
||||||
}
|
}
|
||||||
sendJSON(data, "/user")
|
sendJSON(data, "/user", "POST")
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
log("SUCESS: " + JSON.stringify(data));
|
log("SUCESS: " + JSON.stringify(data));
|
||||||
|
getUserList();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
log("Error posting data");
|
log("Error posting data");
|
||||||
});}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteUser(id) {
|
||||||
|
fetch("/user/" + id, { method: "DELETE", } )
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
log("SUCESS: " + JSON.stringify(data));
|
||||||
|
getUserList();
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
log("Error posting data");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function addHeaderCell(tr, text) {
|
||||||
|
var th = document.createElement('TH');
|
||||||
|
th.innerHTML = text;
|
||||||
|
tr.appendChild(th);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showTable(users) {
|
||||||
|
var t = document.getElementById("usertable");
|
||||||
|
var new_t = document.createElement("TABLE");
|
||||||
|
var header = new_t.createTHead();
|
||||||
|
var tr = header.insertRow();
|
||||||
|
// insertCell creates TD, we want TH
|
||||||
|
addHeaderCell(tr, 'id');
|
||||||
|
addHeaderCell(tr, 'first name');
|
||||||
|
addHeaderCell(tr, 'last name');
|
||||||
|
addHeaderCell(tr, 'action');
|
||||||
|
|
||||||
|
console.log("showTable()");
|
||||||
|
console.log(users);
|
||||||
|
// add the data rows
|
||||||
|
for(var i=0; i<users.length; i++) {
|
||||||
|
var row = new_t.insertRow();
|
||||||
|
var c1 = row.insertCell();
|
||||||
|
c1.innerHTML = users[i].id;
|
||||||
|
var c2 = row.insertCell();
|
||||||
|
c2.innerHTML = users[i].first_name;
|
||||||
|
var c3 = row.insertCell();
|
||||||
|
c3.innerHTML = users[i].last_name;
|
||||||
|
var c4 = row.insertCell();
|
||||||
|
c4.innerHTML = '<button type="button" onclick="deleteUser(' + users[i].id + ');">del</button>';
|
||||||
|
}
|
||||||
|
console.log("before replace");
|
||||||
|
t.innerHTML = new_t.innerHTML;
|
||||||
|
console.log("after replace");
|
||||||
|
}
|
||||||
|
function getUserList() {
|
||||||
|
fetch("/list", { method: "GET", } )
|
||||||
|
.then((response) => response.json())
|
||||||
|
.then((data) => {
|
||||||
|
log("SUCESS: " + JSON.stringify(data));
|
||||||
|
showTable(data);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
log("Error posting data");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
getUserList();
|
||||||
|
}
|
||||||
|
init();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -2,6 +2,7 @@ const std = @import("std");
|
||||||
|
|
||||||
alloc: std.mem.Allocator = undefined,
|
alloc: std.mem.Allocator = undefined,
|
||||||
users: std.AutoHashMap(usize, InternalUser) = undefined,
|
users: std.AutoHashMap(usize, InternalUser) = undefined,
|
||||||
|
count: usize = 0,
|
||||||
|
|
||||||
pub const Self = @This();
|
pub const Self = @This();
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ const InternalUser = struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const User = struct {
|
pub const User = struct {
|
||||||
|
id: usize = 0,
|
||||||
first_name: []const u8,
|
first_name: []const u8,
|
||||||
last_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
|
/// the request will be freed (and reused by facilio) when it's
|
||||||
/// completed, so we take copies of the names
|
/// completed, so we take copies of the names
|
||||||
pub fn addByName(self: *Self, first: ?[]const u8, last: ?[]const u8) !usize {
|
pub fn addByName(self: *Self, first: ?[]const u8, last: ?[]const u8) !usize {
|
||||||
var created = try self.alloc.alloc(InternalUser, 1);
|
// TODO: get rid of the temp allocation here
|
||||||
var user = created[0];
|
var temp = try self.alloc.alloc(InternalUser, 1);
|
||||||
user.id = self.users.count() + 1;
|
defer self.alloc.free(temp);
|
||||||
|
var user = temp[0];
|
||||||
|
self.count = self.count + 1;
|
||||||
|
user.id = self.count;
|
||||||
user.firstnamelen = 0;
|
user.firstnamelen = 0;
|
||||||
user.lastnamelen = 0;
|
user.lastnamelen = 0;
|
||||||
if (first) |firstname| {
|
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 {
|
pub fn delete(self: *Self, id: usize) bool {
|
||||||
if (self.users.get(id)) |pUser| {
|
|
||||||
self.alloc.free(pUser);
|
|
||||||
return self.users.remove(id);
|
return self.users.remove(id);
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(self: *Self, id: usize) ?User {
|
pub fn get(self: *Self, id: usize) ?User {
|
||||||
if (self.users.get(id)) |pUser| {
|
if (self.users.get(id)) |pUser| {
|
||||||
return .{
|
return .{
|
||||||
|
.id = pUser.id,
|
||||||
.first_name = pUser.firstnamebuf[0..pUser.firstnamelen],
|
.first_name = pUser.firstnamebuf[0..pUser.firstnamelen],
|
||||||
.last_name = pUser.lastnamebuf[0..pUser.lastnamelen],
|
.last_name = pUser.lastnamebuf[0..pUser.lastnamelen],
|
||||||
};
|
};
|
||||||
|
@ -63,16 +65,22 @@ pub fn get(self: *Self, id: usize) ?User {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(self: *Self, id: usize, first: ?[]const u8, last: ?[]const u8) bool {
|
pub fn update(
|
||||||
if (self.users.get(id)) |pUser| {
|
self: *Self,
|
||||||
pUser.firstnamelen = 0;
|
id: usize,
|
||||||
pUser.lastnamelen = 0;
|
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| {
|
if (first) |firstname| {
|
||||||
std.mem.copy(u8, pUser.firstnamebuf[0..], firstname);
|
std.mem.copy(u8, pUser.firstnamebuf[0..], firstname);
|
||||||
pUser.firstnamelen = firstname.len;
|
pUser.firstnamelen = firstname.len;
|
||||||
}
|
}
|
||||||
if (last) |lastname| {
|
if (last) |lastname| {
|
||||||
std.mem.copy(u8, pUser.lastname[0..], lastname);
|
std.mem.copy(u8, pUser.lastnamebuf[0..], lastname);
|
||||||
pUser.lastnamelen = lastname.len;
|
pUser.lastnamelen = lastname.len;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -104,6 +112,7 @@ const JsonUserIterator = struct {
|
||||||
pub fn next(this: *This) ?User {
|
pub fn next(this: *This) ?User {
|
||||||
if (this.it.next()) |pUser| {
|
if (this.it.next()) |pUser| {
|
||||||
return User{
|
return User{
|
||||||
|
.id = pUser.id,
|
||||||
.first_name = pUser.firstnamebuf[0..pUser.firstnamelen],
|
.first_name = pUser.firstnamebuf[0..pUser.firstnamelen],
|
||||||
.last_name = pUser.lastnamebuf[0..pUser.lastnamelen],
|
.last_name = pUser.lastnamebuf[0..pUser.lastnamelen],
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue