1
0
Fork 0
mirror of https://github.com/zigzap/zap.git synced 2026-01-29 09:06:58 +00:00
zap/examples/cookies/cookies.zig
renerocksai a0f67ffc6e
Update to Zig 0.16.0-dev (master) compatibility
Adapt codebase to breaking API changes in Zig 0.16.0-dev:

std.Io introduction:
- std.io namespace renamed to std.Io (capitalization)
- std.http.Client now requires io field
- Create std.Io.Threaded at entry points, pass io to functions
- Use std.Io.Writer.fixed() for fixed buffer writers
- Use std.Io.Dir.cwd().access(io, ...) for file access checks

Sleep API:
- std.Thread.sleep / std.time.sleep removed
- Use std.posix.nanosleep(seconds, nanoseconds) instead

JSON API:
- std.json.stringify() -> std.json.Stringify.value()

Time API:
- std.time.nanoTimestamp() removed
- Use std.time.Instant.now() with .since() for durations

File API:
- readFileAlloc parameter order changed, uses std.Io.Limit

Debug API:
- std.debug.writeStackTrace signature changed (removed debugInfo)
- Capture traces by pointer with |*trace| pattern

Refactored Io pattern in tests/examples to create Threaded once
at entry points and pass io: std.Io to helper functions, following
Zig's new convention of treating Io like allocators.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-06 16:11:10 +01:00

131 lines
4.2 KiB
Zig

//!
//! Part of the Zap examples.
//!
//! Build me with `zig build cookies`.
//! Run me with `zig build run-cookies`.
//!
const std = @import("std");
const zap = @import("zap");
// set default log level to .info and ZAP log level to .debug
pub const std_options: std.Options = .{
.log_level = .info,
.log_scope_levels = &[_]std.log.ScopeLevel{
.{ .scope = .zap, .level = .debug },
},
};
// We send ourselves a request with a cookie
fn makeRequest(a: std.mem.Allocator, io: std.Io, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a, .io = io };
defer http_client.deinit();
_ = try http_client.fetch(.{
.location = .{ .url = url },
.method = .GET,
.extra_headers = &.{
.{ .name = "cookie", .value = "ZIG_ZAP=awesome" },
},
});
}
fn makeRequestThread(a: std.mem.Allocator, io: std.Io, url: []const u8) !std.Thread {
return try std.Thread.spawn(.{}, makeRequest, .{ a, io, url });
}
// here we go
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true,
}){};
const allocator = gpa.allocator();
const Handler = struct {
var alloc: std.mem.Allocator = undefined;
pub fn on_request(r: zap.Request) !void {
std.debug.print("\n=====================================================\n", .{});
defer std.debug.print("=====================================================\n\n", .{});
r.parseCookies(false); // url_encoded = false
const cookie_count = r.getCookiesCount();
std.log.info("cookie_count: {}", .{cookie_count});
// iterate over all cookies as strings
var strCookies = r.cookiesToOwnedStrList(alloc) catch unreachable;
defer strCookies.deinit();
std.debug.print("\n", .{});
for (strCookies.items) |kv| {
std.log.info("CookieStr `{s}` is `{s}`", .{ kv.key, kv.value });
// we don't need to deinit kv.key and kv.value because we requested always_alloc=false
// so they are just slices into the request buffer
}
std.debug.print("\n", .{});
// // iterate over all cookies
var cookies = r.cookiesToOwnedList(alloc) catch unreachable;
defer cookies.deinit();
for (cookies.items) |kv| {
std.log.info("cookie `{s}` is {any}", .{ kv.key, kv.value });
}
// let's get cookie "ZIG_ZAP" by name
std.debug.print("\n", .{});
if (r.getCookieStr(alloc, "ZIG_ZAP")) |maybe_str| {
if (maybe_str) |s| {
defer alloc.free(s);
std.log.info("Cookie ZIG_ZAP = {s}", .{s});
} else {
std.log.info("Cookie ZIG_ZAP not found!", .{});
}
} else |err| {
std.log.err("ERROR!", .{});
std.log.err("cannot check for `ZIG_ZAP` cookie: {any}", .{err});
}
r.setCookie(.{
.name = "rene",
.value = "rocksai",
.path = "/xxx",
.domain = "yyy",
// if we leave .max_age_s = 0 -> session cookie
.max_age_s = 60,
//
// check out other params: domain, path, secure, http_only
}) catch |err| {
std.log.err("ERROR!", .{});
std.log.err("cannot set cookie: {any}", .{err});
};
r.sendBody("Hello") catch unreachable;
}
};
Handler.alloc = allocator;
// setup listener
var listener = zap.HttpListener.init(
.{
.port = 3000,
.on_request = Handler.on_request,
.log = false,
.max_clients = 10,
.max_body_size = 1 * 1024,
},
);
try listener.listen();
std.log.info("\n\nTerminate with CTRL+C", .{});
var threaded = std.Io.Threaded.init(allocator);
defer threaded.deinit();
const io = threaded.io();
const thread = try makeRequestThread(allocator, io, "http://127.0.0.1:3000");
defer thread.join();
zap.start(.{
.threads = 1,
.workers = 1,
});
}