1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
|
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;
}
|