srctree

Jeremy Hertel parent 0c8e59e9 0486c686
add basic api example

build.zig added: 130, removed: 2, total 128
@@ -47,6 +47,7 @@ pub fn build(b: *std.Build) !void {
"endpoint",
"auth-cookie",
"request-userdata",
"api",
};
for (examples) |example| {
const path = try std.fmt.allocPrint(b.allocator, "examples/{s}.zig", .{example});
 
filename was Deleted added: 130, removed: 2, total 128
@@ -0,0 +1,127 @@
//! Provides a basic example of a rest api using verse.
 
const std = @import("std");
const ArrayListUnmanaged = std.ArrayListUnmanaged;
const verse = @import("verse");
const Router = verse.Router;
const RouteMap = verse.Router.RouteMap;
const BuildFn = Router.BuildFn;
 
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);
};
}