Basic api server
This commit is contained in:
parent
255a11bc8b
commit
ccf79febe4
2 changed files with 72 additions and 7 deletions
65
src/main/api.zig
Normal file
65
src/main/api.zig
Normal 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);
|
||||||
|
}
|
||||||
|
};
|
|
@ -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),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue