-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathapi.zig
128 lines (104 loc) · 3.46 KB
/
api.zig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! Provides a basic example of a rest api using verse.
/// The Verse router can support more complex routing patterns and can
/// route different request methods to separate functions so you can easily
/// expose a custom REST interface/API.
const routes = Router.Routes(&[_]Router.Match{
Router.Match{
.name = "users",
.methods = .{
.GET = .{ .build = users },
.POST = .{ .build = addUser },
.DELETE = .{ .build = deleteUser },
},
},
});
const Role = enum {
user,
admin,
};
const User = struct {
id: u32,
name: []const u8,
age: u8,
role: Role,
active: bool,
};
const CreateUserRequest = struct {
name: []const u8,
age: u8,
role: Role,
active: bool,
};
var user_list: ArrayListUnmanaged(User) = undefined;
var alloc: std.mem.Allocator = undefined;
/// Returns the list of users.
fn users(frame: *verse.Frame) !void {
try frame.sendJSON(.ok, user_list.items);
}
/// Adds a new user to the list.
fn addUser(frame: *verse.Frame) !void {
// validate that the post data is in the expected format
const request = verse.RequestData.RequestData(CreateUserRequest).init(frame.request.data) catch {
try frame.sendJSON(.bad_request, .{ .message = "bad request data" });
return;
};
var id: u32 = 1;
if (user_list.items.len > 0) {
id = user_list.items[user_list.items.len - 1].id + 1;
}
const user = User{
.id = id,
.name = try alloc.dupe(u8, request.name),
.age = request.age,
.role = request.role,
.active = request.active,
};
try user_list.append(alloc, user);
try frame.sendJSON(.created, user);
}
/// Deletes a user from the list.
fn deleteUser(frame: *verse.Frame) !void {
_ = frame.uri.next(); // skip /users
const id_str = frame.uri.next(); // get the id from the url, if null then the caller didn't provide one
if (id_str == null) {
try frame.sendJSON(.bad_request, .{ .message = "missing id" });
return;
}
const id = std.fmt.parseInt(u32, id_str.?, 10) catch {
try frame.sendJSON(.bad_request, .{ .message = "invalid id" });
return;
};
var found = false;
for (0..user_list.items.len) |i| {
const user = user_list.items[i];
if (user.id == id) {
_ = user_list.swapRemove(i);
found = true;
break;
}
}
if (!found) {
try frame.sendJSON(.not_found, .{ .message = "user not found" });
return;
}
try frame.sendJSON(.ok, .{ .message = "success" });
}
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
alloc = gpa.allocator();
user_list = ArrayListUnmanaged(User){};
try user_list.append(alloc, .{ .id = 0, .name = "John Doe", .age = 23, .role = .user, .active = true });
try user_list.append(alloc, .{ .id = 1, .name = "Billy Joe", .age = 25, .role = .user, .active = false });
try user_list.append(alloc, .{ .id = 2, .name = "Jane Smith", .age = 28, .role = .admin, .active = true });
defer user_list.deinit(alloc);
var server = try verse.Server.init(alloc, routes, .{ .mode = .{ .http = .{ .port = 8080 } } });
server.serve() catch |err| {
std.debug.print("error: {any}", .{err});
std.posix.exit(1);
};
}
const std = @import("std");
const ArrayListUnmanaged = std.ArrayListUnmanaged;
const verse = @import("verse");
const Router = verse.Router;