Basic api server

This commit is contained in:
jaina heartles 2022-07-12 20:40:48 -07:00
parent 255a11bc8b
commit ccf79febe4
2 changed files with 72 additions and 7 deletions

65
src/main/api.zig Normal file
View file

@ -0,0 +1,65 @@
const std = @import("std");
const db = @import("./db.zig");
pub const models = @import("./models.zig");
pub const free = db.free;
pub const Id = []const u8;
pub fn CreateInfo(comptime T: type) type {
const t_fields = std.meta.fields(T);
var fields: [t_fields.len - 1]std.builtin.Type.StructField = undefined;
var count = 0;
inline for (t_fields) |f| {
if (std.mem.eql(u8, f.name, "id")) continue;
fields[count] = f;
count += 1;
}
return @Type(.{ .Struct = .{
.layout = .Auto,
.fields = &fields,
.decls = &[0]std.builtin.Type.Declaration{},
.is_tuple = false,
} });
}
fn reify(comptime T: type, id: Id, val: CreateInfo(T)) T {
var result: T = undefined;
result.id = id;
inline for (std.meta.fields(CreateInfo(T))) |f| {
@field(result, f.name) = @field(val, f.name);
}
return result;
}
const ApiServer = struct {
db: db.Database,
last_id: u64 = 0,
pub fn init(alloc: std.mem.Allocator) !ApiServer {
return ApiServer{
.db = try db.Database.init(alloc),
};
}
fn genId(self: *ApiServer, alloc: std.mem.Allocator) ![]const u8 {
self.last_id += 1;
return std.fmt.allocPrint(alloc, "{}", .{self.last_id});
}
pub fn createNote(self: *ApiServer, info: CreateInfo(models.Note), alloc: std.mem.Allocator) !models.Note {
const id = try self.genId(alloc);
const note = reify(models.Note, id, info);
try self.db.putNote(note);
return id;
}
pub fn getNote(self: *ApiServer, id: Id, alloc: std.mem.Allocator) !?models.Note {
return self.db.getNote(id, alloc);
}
};

View file

@ -1,7 +1,7 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin"); const builtin = @import("builtin");
const http = @import("http"); const http = @import("http");
const db = @import("./db.zig"); const api = @import("./api.zig");
const models = @import("./models.zig"); const models = @import("./models.zig");
// this thing is overcomplicated and weird. stop this // this thing is overcomplicated and weird. stop this
@ -49,18 +49,18 @@ fn respondJson(ctx: *http.server.Context, status: http.Status, value: anytype, a
fn createNote(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !void { fn createNote(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !void {
const body = ctx.request.body orelse return respondJson(ctx, .bad_request, .{ .@"error" = "no note body provided" }, srv.alloc); const body = ctx.request.body orelse return respondJson(ctx, .bad_request, .{ .@"error" = "no note body provided" }, srv.alloc);
var tokens = std.json.TokenStream.init(body); var tokens = std.json.TokenStream.init(body);
const note = try std.json.parse(models.Note, &tokens, .{ .allocator = srv.alloc }); const note = try std.json.parse(api.CreateInfo(models.Note), &tokens, .{ .allocator = srv.alloc });
defer std.json.parseFree(models.Note, note, .{ .allocator = srv.alloc }); defer std.json.parseFree(models.Note, note, .{ .allocator = srv.alloc });
try srv.db.putNote(note); try srv.api.createNote(note);
try respondJson(ctx, .created, note, srv.alloc); try respondJson(ctx, .created, note, srv.alloc);
} }
fn getNote(srv: *RequestServer, ctx: *http.server.Context, args: RouteArgs) !void { fn getNote(srv: *RequestServer, ctx: *http.server.Context, args: RouteArgs) !void {
const id = args.get("id") orelse return error.NotFound; const id = args.get("id") orelse return error.NotFound;
const note = (try srv.db.getNote(id, srv.alloc)) orelse return error.NotFound; const note = (try srv.api.getNote(id, srv.alloc)) orelse return error.NotFound;
defer db.free(srv.alloc, note); defer api.free(srv.alloc, note);
try respondJson(ctx, .ok, note, srv.alloc); try respondJson(ctx, .ok, note, srv.alloc);
} }
@ -71,12 +71,12 @@ fn healthcheck(srv: *RequestServer, ctx: *http.server.Context, _: RouteArgs) !vo
const RequestServer = struct { const RequestServer = struct {
alloc: std.mem.Allocator, alloc: std.mem.Allocator,
db: db.Database, api: api.ApiServer,
fn init(alloc: std.mem.Allocator) !RequestServer { fn init(alloc: std.mem.Allocator) !RequestServer {
return RequestServer{ return RequestServer{
.alloc = alloc, .alloc = alloc,
.db = try db.Database.init(alloc), .api = try api.ApiServer.init(alloc),
}; };
} }