const z = @import( "std" ); const u = @import( "util.zig" ); const zap = @import( "zap" ); const jwt = @import( "jwt" ); const uuid = @import( "uuid" ); const alloc = u.alloc; const JWT = jwt.JWT; const memcmp = z.mem.eql; const Status = zap.StatusCode; const Request = zap.Request; pub const ErrorResponse = struct { status: []const u8 = "error", msg: []const u8 }; const OkResponseTemplate = struct { status: []const u8 = "ok" }; fn MergeOk( comptime t: type ) type { const ti = @typeInfo( t ); comptime if( ti.Struct.is_tuple ) return OkResponseTemplate; return u.MergeTypes( OkResponseTemplate, t ); } pub fn OkResponse( t: anytype ) MergeOk(@TypeOf(t)) { const ret: MergeOk(@TypeOf(t)) = t; return ret; } pub fn sendJson( r: Request, status: Status, t: anytype ) void { r.setStatus( status ); const encoded = u.jsonStringify( t ) catch |e| { z.debug.print( "Failed to encode JSON: {any} {any} {any}\n", .{t, e, @errorReturnTrace()} ); return; }; defer alloc.free( encoded ); r.sendJson( encoded ) catch |e| { z.debug.print( "Failed to send body: {s} {any} {any}\n", .{encoded, e, @errorReturnTrace()} ); }; } pub fn sendJsonChunk( r: Request, status: Status, t: anytype ) void { r.setStatus( status ); const encoded = u.jsonStringify( t ) catch |e| { z.debug.print( "Failed to encode JSON: {any} {any} {any}\n", .{t, e, @errorReturnTrace()} ); return; }; defer alloc.free( encoded ); z.debug.print( "sending {s}\n", .{ encoded } ); r.sendChunk( encoded ) catch |e| { z.debug.print( "Failed to send body: {s} {any} {any}\n", .{encoded, e, @errorReturnTrace()} ); }; } pub fn handleInvalidPostReq( r: Request ) bool { if( r.method == null ) { sendJson( r, .method_not_allowed, .{ .status = "error", .msg = "method is null" } ); return true; } if( r.methodAsEnum() != .POST ) { if( r.methodAsEnum() == .OPTIONS ) { r.sendBody( "" ) catch {}; return true; } sendJson( r, .method_not_allowed, .{ .status = "error", .msg = "method not allowed" } ); return true; } if( r.body == null ) { sendJson( r, .bad_request, .{ .status = "error", .msg = "body is null" } ); return true; } r.parseBody() catch { sendJson( r, .bad_request, .{ .status = "error", .msg = "body is not valid json" } ); return true; }; return false; } ///caller has to free pub fn getJwtSecret() ![]const u8 { return u.readFile( "../data/jwt_secret.txt" ); } ///caller has to free pub fn parseJWT( t: type, str: []const u8 ) !JWT(t) { const key = try getJwtSecret(); defer alloc.free( key ); const token = try jwt.decode( alloc, t, str, .{ .secret = key }, .{}, ); return token; } ///caller has to free pub fn encodeJWT( data: anytype ) ![]const u8 { const secret = try getJwtSecret(); defer alloc.free( secret ); const token = try jwt.encode( alloc, .{ .alg = .HS256 }, data, .{ .secret = secret } ); return token; } pub fn uuidv4() uuid.urn.Urn { const id = uuid.v4.new(); const urn = uuid.urn.serialize(id); return urn; }