rluv-zerver/src/http_handler.zig
2023-07-27 12:30:56 -06:00

131 lines
4.1 KiB
Zig

const std = @import("std");
const httpz = @import(".deps/http.zig/src/httpz.zig");
const models = @import("db/models.zig");
const ztime = @import(".deps/time.zig");
const utils = @import("utils.zig");
const budget = @import("routes/budget.zig");
const auth = @import("routes/auth.zig");
const user = @import("routes/user.zig");
const trans = @import("routes/transactions.zig");
const dash = @import("routes/dashboard.zig");
const note = @import("routes/shared_note.zig");
const Db = @import("db/db.zig").Db;
var db: ?Db = null;
pub fn getDb() *Db {
return &db.?;
}
pub fn startHttpServer() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
// db = try Db.init(allocator, null);
// defer db.deinit();
var args = try std.process.argsWithAllocator(allocator);
// skip program name
_ = args.skip();
while (args.next()) |arg| {
if (std.mem.eql(u8, arg, "--db_path")) {
const path = args.next();
// std.debug.print("Got path: {any}", .{path});
if (path) |db_path| {
db = try Db.init(allocator, db_path, null);
} else {
std.log.err("Db path not provided after arg", .{});
return;
}
}
if (std.mem.eql(u8, arg, "--make-migration")) {
if (db == null) {
std.log.err("Cannot migrate, provide db path first", .{});
return;
}
try db.?.wipeAndMigrateDb();
}
}
if (db == null) {
db = try Db.init(allocator, null, null);
}
defer db.?.deinit();
var server = try httpz.Server().init(allocator, .{ .port = 8081 });
// overwrite the default notFound handler
server.notFound(notFound);
// overwrite the default error handler
server.errorHandler(errorHandler);
var router = server.router();
router.post("/auth/login", user.login);
router.post("/auth/signup", user.signup);
// router.get("/user/:id", user.getUser);
router.put("/user", user.putUser);
// router.delete("/user/:id", user.deleteUser);
router.get("/shared_notes/:limit", note.getSharedNotes);
router.put("/shared_notes", note.putSharedNote);
router.post("/shared_notes", note.postSharedNote);
// router.get("/budget/:id", budget.getBudget);
// router.put("/budget", budget.putBudget);
// router.post("/budget", budget.postBudget);
router.put("/budget_category", budget.putBudgetCategory);
router.post("/budget_category", budget.postBudgetCategory);
router.post("/transactions", trans.postTransaction);
router.put("/transactions", trans.putTransaction);
router.get("/dashboard", dash.getDashboard);
std.debug.print("Starting http server listening on port {}\n", .{8081});
// start the server in the current thread, blocking.
try server.listen();
}
fn notFound(_: *httpz.Request, res: *httpz.Response) !void {
res.status = 404;
// you can set the body directly to a []u8, but note that the memory
// must be valid beyond your handler. Use the res.arena if you need to allocate
// memory for the body.
res.body = "Not Found";
}
// note that the error handler return `void` and not `!void`
fn errorHandler(req: *httpz.Request, res: *httpz.Response, err: anyerror) void {
res.status = 500;
res.body = "Internal Server Error";
std.log.warn("httpz: unhandled exception for request: {s}\nErr: {}", .{ req.url.raw, err });
}
pub fn returnError(message: ?[]const u8, comptime statusCode: u16, res: *httpz.Response) void {
comptime {
if (statusCode > 500 or statusCode < 200) {
@compileError("Failed responses must have status codes between 200 and 500");
}
}
res.status = statusCode;
res.json(.{ .success = false, .message = message }, .{}) catch |err| {
std.log.warn("Couldnt create error body: {}", .{err});
res.body = "{ \"success\": false";
};
}
pub fn returnData(data: anytype, res: *httpz.Response) !void {
const body = utils.structConcatFields(data, .{ .success = true });
res.status = 200;
try res.json(body, .{});
}