diff --git a/README.md b/README.md index 203034b..e882c95 100644 --- a/README.md +++ b/README.md @@ -223,309 +223,3 @@ pub fn main() !void { } ``` -### [serve](examples/serve/serve.zig) - -```zig -const std = @import("std"); -const zap = @import("zap"); - -fn on_request(r: zap.SimpleRequest) void { - r.setStatus(404); - _ = r.sendBody("

404 - File not found

"); -} - -pub fn main() !void { - var listener = zap.SimpleHttpListener.init(.{ - .port = 3000, - .on_request = on_request, - .public_folder = std.mem.span("examples/serve"), - .log = true, - }); - try listener.listen(); - - std.debug.print("Listening on 0.0.0.0:3000\n", .{}); - - // start worker threads - zap.start(.{ - .threads = 2, - .workers = 2, - }); -} -``` - -### [routes](examples/routes/routes.zig) - -```zig -const std = @import("std"); -const zap = @import("zap"); - -fn dispatch_routes(r: zap.SimpleRequest) void { - // dispatch - if (r.path) |the_path| { - if (routes.get(the_path)) |foo| { - foo(r); - } - } - // or default: present menu - _ = r.sendBody( - \\ - \\ - \\

static

- \\

dynamic

- \\ - \\ - ); -} - -fn static_site(r: zap.SimpleRequest) void { - _ = r.sendBody("

Hello from STATIC ZAP!

"); -} - -var dynamic_counter: i32 = 0; -fn dynamic_site(r: zap.SimpleRequest) void { - dynamic_counter += 1; - var buf: [128]u8 = undefined; - const filled_buf = std.fmt.bufPrintZ( - &buf, - "

Hello # {d} from DYNAMIC ZAP!!!

", - .{dynamic_counter}, - ) catch "ERROR"; - _ = r.sendBody(std.mem.span(filled_buf)); -} - -fn setup_routes(a: std.mem.Allocator) !void { - routes = std.StringHashMap(zap.SimpleHttpRequestFn).init(a); - try routes.put("/static", static_site); - try routes.put("/dynamic", dynamic_site); -} - -var routes: std.StringHashMap(zap.SimpleHttpRequestFn) = undefined; - -pub fn main() !void { - try setup_routes(std.heap.page_allocator); - var listener = zap.SimpleHttpListener.init(.{ - .port = 3000, - .on_request = dispatch_routes, - .log = true, - }); - try listener.listen(); - - std.debug.print("Listening on 0.0.0.0:3000\n", .{}); - - zap.start(.{ - .threads = 2, - .workers = 2, - }); -} -``` - -### [hello_json](examples/hello_json/hello_json.zig) - -```zig -const std = @import("std"); -const zap = @import("zap"); - -const User = struct { - first_name: ?[]const u8 = null, - last_name: ?[]const u8 = null, -}; - -fn on_request(r: zap.SimpleRequest) void { - if (!std.mem.eql(u8, r.method.?, "GET")) - return; - - // /user/n - if (r.path) |the_path| { - if (the_path.len < 7 or !std.mem.startsWith(u8, the_path, "/user/")) - return; - - const user_id: usize = @intCast(usize, the_path[6] - 0x30); - const user = users.get(user_id); - - var json_to_send: []const u8 = undefined; - if (stringify(user, .{})) |json| { - json_to_send = json; - } else { - json_to_send = "null"; - } - std.debug.print("<< json: {s}\n", .{json_to_send}); - r.setContentType(.JSON); - _ = r.sendBody(json_to_send); - } -} - -const UserMap = std.AutoHashMap(usize, User); - -var users: UserMap = undefined; -fn setupUserData(a: std.mem.Allocator) !void { - users = UserMap.init(a); - try users.put(1, .{ .first_name = "renerocksai" }); - try users.put(2, .{ .first_name = "Your", .last_name = "Mom" }); -} - -fn stringify(value: anytype, options: std.json.StringifyOptions) ?[]const u8 { - var buf: [100]u8 = undefined; - var fba = std.heap.FixedBufferAllocator.init(&buf); - var string = std.ArrayList(u8).init(fba.allocator()); - if (std.json.stringify(value, options, string.writer())) { - return string.items; - } else |_| { // error - return null; - } -} - -pub fn main() !void { - var a = std.heap.page_allocator; - try setupUserData(a); - var listener = zap.SimpleHttpListener.init(.{ - .port = 3000, - .on_request = on_request, - .log = false, - }); - try listener.listen(); - - std.debug.print("Listening on 0.0.0.0:3000\n", .{}); - - // start worker threads - zap.start(.{ - .threads = 2, - .workers = 2, - }); -} -``` - -### [endpoint](examples/endpoint/) - -The following only shows the GET functionality implemented on the `/users/` -See [endpoint](examples/endpoint/) for a complete -example, including an HTML + JavaScript frontend. - -[`main.zig`](examples/endpoint/main.zig): - -```zig - -const std = @import("std"); -const zap = @import("zap"); -const Endpoint = @import("endpoint.zig"); - -pub fn main() !void { - const allocator = std.heap.page_allocator; - // setup listener - var listener = zap.SimpleEndpointListener.init( - allocator, - .{ - .port = 3000, - .on_request = null, - .log = true, - .public_folder = "./examples/endpoint/html", - }, - ); - - Endpoint.init(allocator, "/users"); - - // add endpoint - try listener.addEndpoint(Endpoint.getUserEndpoint()); - - // fake some users - var uid: usize = undefined; - uid = try Endpoint.getUsers().addByName("renerocksai", null); - uid = try Endpoint.getUsers().addByName("renerocksai", "your mom"); - - // listen - try listener.listen(); - - std.debug.print("Listening on 0.0.0.0:3000\n", .{}); - - // and run - zap.start(.{ - .threads = 2, - .workers = 1, // to stay in process; users list shared between threads - }); -} -``` - - -[`endpoint.zig`](examples/endpoint/endpoint.zig): - -```zig -const std = @import("std"); -const zap = @import("zap"); -const Users = @import("users.zig"); -const User = Users.User; - -// the Endpoint - -pub const Self = @This(); - -var alloc: std.mem.Allocator = undefined; -var endpoint: zap.SimpleEndpoint = undefined; -var users: Users = undefined; - -pub fn init( - a: std.mem.Allocator, - user_path: []const u8, -) void { - users = Users.init(a); - alloc = a; - endpoint = zap.SimpleEndpoint.init(.{ - .path = user_path, - .get = getUser, - .post = postUser, - .put = putUser, - .delete = deleteUser, - }); -} - -pub fn getUsers() *Users { - return &users; -} - -pub fn getUserEndpoint() *zap.SimpleEndpoint { - return &endpoint; -} - -fn userIdFromPath(path: []const u8) ?usize { - if (path.len >= endpoint.settings.path.len + 2) { - if (path[endpoint.settings.path.len] != '/') { - return null; - } - const idstr = path[endpoint.settings.path.len + 1 ..]; - return std.fmt.parseUnsigned(usize, idstr, 10) catch null; - } - return null; -} - -fn getUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { - if (r.path) |path| { - // /users - if (path.len == e.settings.path.len) { - return listUsers(e, r); - } - if (userIdFromPath(path)) |id| { - if (users.get(id)) |user| { - if (zap.stringify(user, .{})) |json| { - _ = r.sendJson(json); - } - } - } - } -} - -fn listUsers(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { - _ = e; - var l: std.ArrayList(User) = std.ArrayList(User).init(alloc); - if (users.list(&l)) {} else |_| { - return; - } - if (zap.stringifyArrayList(User, &l, .{})) |maybe_json| { - if (maybe_json) |json| { - _ = r.sendJson(json); - } - } else |_| { - return; - } -} - -// ... -``` -