1
0
Fork 0
mirror of https://github.com/zigzap/zap.git synced 2025-10-20 15:14:08 +00:00

more sane endpoints example

This commit is contained in:
Rene Schallner 2023-01-18 14:26:01 +01:00
parent 3fa538081e
commit c8f9a18dc0
5 changed files with 82 additions and 50 deletions

View file

@ -33,9 +33,8 @@ Here's what works:
- **[hello_json](examples/hello_json/hello_json.zig)**: serves you json - **[hello_json](examples/hello_json/hello_json.zig)**: serves you json
dependent on HTTP path dependent on HTTP path
- **[endpoints](examples/endpoints/)**: a simple JSON REST API example featuring - **[endpoints](examples/endpoints/)**: a simple JSON REST API example featuring
a `/users` endpoint for PUTting/DELETE-ing/GET-ting/POST-ing users and a a `/users` endpoint for PUTting/DELETE-ing/GET-ting/POST-ing and listing
`/list` endpoint returning the entire user list on GET, together with a static users, together with a static HTML and JavaScript frontend to play with.
HTML and JavaScript frontend to play around with.
I'll continue wrapping more of facil.io's functionality and adding stuff to zap I'll continue wrapping more of facil.io's functionality and adding stuff to zap
to a point where I can use it as the JSON REST API backend for real research to a point where I can use it as the JSON REST API backend for real research
@ -421,11 +420,10 @@ pub fn main() !void {
}, },
); );
Endpoints.init(allocator, "/user", "/list"); Endpoints.init(allocator, "/users");
// add endpoints // add endpoint
try listener.addEndpoint(Endpoints.getUserEndpoint()); try listener.addEndpoint(Endpoints.getUserEndpoint());
try listener.addEndpoint(Endpoints.getUserListEndpoint());
// fake some users // fake some users
var uid: usize = undefined; var uid: usize = undefined;
@ -454,34 +452,26 @@ const zap = @import("zap");
const Users = @import("users.zig"); const Users = @import("users.zig");
const User = Users.User; const User = Users.User;
// the Endpoints // the Endpoint
pub const Self = @This(); pub const Self = @This();
var alloc: std.mem.Allocator = undefined; var alloc: std.mem.Allocator = undefined;
var endpoint: zap.SimpleEndpoint = undefined; var endpoint: zap.SimpleEndpoint = undefined;
var list_endpoint: zap.SimpleEndpoint = undefined;
var users: Users = undefined; var users: Users = undefined;
pub fn init( pub fn init(
a: std.mem.Allocator, a: std.mem.Allocator,
user_path: []const u8, user_path: []const u8,
userlist_path: []const u8,
) void { ) void {
users = Users.init(a); users = Users.init(a);
alloc = a; alloc = a;
endpoint = zap.SimpleEndpoint.init(.{ endpoint = zap.SimpleEndpoint.init(.{
.path = user_path, .path = user_path,
.get = getUser, .get = getUser,
.post = null, .post = postUser,
.put = null, .put = putUser,
.delete = null, .delete = deleteUser,
});
list_endpoint = zap.SimpleEndpoint.init(.{
.path = userlist_path,
.get = listUsers,
.post = null,
.put = null,
.delete = null,
}); });
} }
@ -493,10 +483,6 @@ pub fn getUserEndpoint() *zap.SimpleEndpoint {
return &endpoint; return &endpoint;
} }
pub fn getUserListEndpoint() *zap.SimpleEndpoint {
return &list_endpoint;
}
fn userIdFromPath(path: []const u8) ?usize { fn userIdFromPath(path: []const u8) ?usize {
if (path.len >= endpoint.settings.path.len + 2) { if (path.len >= endpoint.settings.path.len + 2) {
if (path[endpoint.settings.path.len] != '/') { if (path[endpoint.settings.path.len] != '/') {
@ -508,9 +494,12 @@ fn userIdFromPath(path: []const u8) ?usize {
return null; return null;
} }
pub fn getUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { fn getUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void {
_ = e;
if (r.path) |path| { if (r.path) |path| {
// /users
if (path.len == e.settings.path.len) {
return listUsers(e, r);
}
if (userIdFromPath(path)) |id| { if (userIdFromPath(path)) |id| {
if (users.get(id)) |user| { if (users.get(id)) |user| {
if (zap.stringify(user, .{})) |json| { if (zap.stringify(user, .{})) |json| {
@ -521,13 +510,13 @@ pub fn getUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void {
} }
} }
pub fn listUsers(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { fn listUsers(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void {
_ = e; _ = e;
var l: std.ArrayList(User) = std.ArrayList(User).init(alloc); var l: std.ArrayList(User) = std.ArrayList(User).init(alloc);
if (users.list(&l)) {} else |_| { if (users.list(&l)) {} else |_| {
return; return;
} }
if (zap.stringifyArrayList(std.ArrayList(User, &l, .{})) |maybe_json| { if (zap.stringifyArrayList(User, &l, .{})) |maybe_json| {
if (maybe_json) |json| { if (maybe_json) |json| {
_ = r.sendJson(json); _ = r.sendJson(json);
} }
@ -535,5 +524,7 @@ pub fn listUsers(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void {
return; return;
} }
} }
// ...
``` ```

View file

@ -3,19 +3,17 @@ const zap = @import("zap");
const Users = @import("users.zig"); const Users = @import("users.zig");
const User = Users.User; const User = Users.User;
// the Endpoints // the Endpoint
pub const Self = @This(); pub const Self = @This();
var alloc: std.mem.Allocator = undefined; var alloc: std.mem.Allocator = undefined;
var endpoint: zap.SimpleEndpoint = undefined; var endpoint: zap.SimpleEndpoint = undefined;
var list_endpoint: zap.SimpleEndpoint = undefined;
var users: Users = undefined; var users: Users = undefined;
pub fn init( pub fn init(
a: std.mem.Allocator, a: std.mem.Allocator,
user_path: []const u8, user_path: []const u8,
userlist_path: []const u8,
) void { ) void {
users = Users.init(a); users = Users.init(a);
alloc = a; alloc = a;
@ -26,13 +24,6 @@ pub fn init(
.put = putUser, .put = putUser,
.delete = deleteUser, .delete = deleteUser,
}); });
list_endpoint = zap.SimpleEndpoint.init(.{
.path = userlist_path,
.get = listUsers,
.post = null,
.put = null,
.delete = null,
});
} }
pub fn getUsers() *Users { pub fn getUsers() *Users {
@ -43,10 +34,6 @@ pub fn getUserEndpoint() *zap.SimpleEndpoint {
return &endpoint; return &endpoint;
} }
pub fn getUserListEndpoint() *zap.SimpleEndpoint {
return &list_endpoint;
}
fn userIdFromPath(path: []const u8) ?usize { fn userIdFromPath(path: []const u8) ?usize {
if (path.len >= endpoint.settings.path.len + 2) { if (path.len >= endpoint.settings.path.len + 2) {
if (path[endpoint.settings.path.len] != '/') { if (path[endpoint.settings.path.len] != '/') {
@ -59,8 +46,11 @@ fn userIdFromPath(path: []const u8) ?usize {
} }
fn getUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void { fn getUser(e: *zap.SimpleEndpoint, r: zap.SimpleRequest) void {
_ = e;
if (r.path) |path| { if (r.path) |path| {
// /users
if (path.len == e.settings.path.len) {
return listUsers(e, r);
}
if (userIdFromPath(path)) |id| { if (userIdFromPath(path)) |id| {
if (users.get(id)) |user| { if (users.get(id)) |user| {
if (zap.stringify(user, .{})) |json| { if (zap.stringify(user, .{})) |json| {

View file

@ -104,7 +104,7 @@
</table> </table>
</div> </div>
<div class="center"> <div class="center">
<p><a href="/list">Show JSON for all users</a></p> <p><a href="/users">Show JSON for all users</a></p>
</div> </div>
<div style="padding:20px; margin-top: 1rem;"> <div style="padding:20px; margin-top: 1rem;">
<label style="margin-bottom: 10px;">Log Output:</label> <label style="margin-bottom: 10px;">Log Output:</label>
@ -155,7 +155,7 @@
first_name: first_name, first_name: first_name,
last_name: last_name, last_name: last_name,
} }
sendJSON(data, "/user", "POST") sendJSON(data, "/users", "POST")
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
log("SUCESS: " + JSON.stringify(data)); log("SUCESS: " + JSON.stringify(data));
@ -167,7 +167,7 @@
} }
function deleteUser(id) { function deleteUser(id) {
fetch("/user/" + id, { method: "DELETE", } ) fetch("/users/" + id, { method: "DELETE", } )
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
log("SUCESS: " + JSON.stringify(data)); log("SUCESS: " + JSON.stringify(data));
@ -186,7 +186,7 @@
first_name: firstname, first_name: firstname,
last_name: lastname, last_name: lastname,
} }
sendJSON(data, "/user/" + id, "PUT") sendJSON(data, "/users/" + id, "PUT")
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
log("SUCESS: " + JSON.stringify(data)); log("SUCESS: " + JSON.stringify(data));
@ -242,7 +242,7 @@
function getUserList() { function getUserList() {
fetch("/list", { method: "GET", } ) fetch("/users", { method: "GET", } )
.then((response) => response.json()) .then((response) => response.json())
.then((data) => { .then((data) => {
log("SUCESS: " + JSON.stringify(data)); log("SUCESS: " + JSON.stringify(data));

View file

@ -15,11 +15,10 @@ pub fn main() !void {
}, },
); );
Endpoints.init(allocator, "/user", "/list"); Endpoints.init(allocator, "/users");
// add endpoints // add endpoint
try listener.addEndpoint(Endpoints.getUserEndpoint()); try listener.addEndpoint(Endpoints.getUserEndpoint());
try listener.addEndpoint(Endpoints.getUserListEndpoint());
// fake some users // fake some users
var uid: usize = undefined; var uid: usize = undefined;

52
wrk/other_measurements.md Normal file
View file

@ -0,0 +1,52 @@
# other measurements
## zap wrk 'example' with and without logging
**NO** performance regressions observable:
With `logging=true`:
```
[nix-shell:~/code/github.com/renerocksai/zap]$ ./wrk/measure.sh zig > out 2> /dev/null
[nix-shell:~/code/github.com/renerocksai/zap]$ cat out
========================================================================
zig
========================================================================
Running 10s test @ http://127.0.0.1:3000
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 343.91us 286.75us 18.37ms 95.58%
Req/Sec 162.61k 3.61k 174.96k 76.75%
Latency Distribution
50% 302.00us
75% 342.00us
90% 572.00us
99% 697.00us
6470789 requests in 10.01s, 0.96GB read
Requests/sec: 646459.59
Transfer/sec: 98.03MB
```
With `logging=false`:
```
[nix-shell:~/code/github.com/renerocksai/zap]$ ./wrk/measure.sh zig
Listening on 0.0.0.0:3000
========================================================================
zig
========================================================================
Running 10s test @ http://127.0.0.1:3000
4 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 336.10us 122.28us 14.67ms 88.55%
Req/Sec 159.82k 7.71k 176.75k 56.00%
Latency Distribution
50% 310.00us
75% 343.00us
90% 425.00us
99% 699.00us
6359415 requests in 10.01s, 0.94GB read
Requests/sec: 635186.96
Transfer/sec: 96.32MB
```