From b988454a72aa27b8a723cf6683a19b657ade0321 Mon Sep 17 00:00:00 2001 From: Rene Schallner Date: Sat, 13 May 2023 22:30:45 +0200 Subject: [PATCH] added example for sendFile --- README.md | 2 ++ build.zig | 5 +--- examples/sendfile/sendfile.zig | 46 ++++++++++++++++++++++++++++++++++ examples/sendfile/testfile.txt | 1 + src/tests/test_sendfile.zig | 4 +-- targets.txt | 1 + 6 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 examples/sendfile/sendfile.zig create mode 100644 examples/sendfile/testfile.txt diff --git a/README.md b/README.md index 6f82ec6..fc453c9 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,8 @@ Here's what works: dispatching on the HTTP path - **[serve](examples/serve/serve.zig)**: the traditional static web server with optional dynamic request handling +- **[sendfile](examples/sendfile/sendfile.zig)**: simple example of how to send + a file, honoring compression headers, etc. - **[hello_json](examples/hello_json/hello_json.zig)**: serves you json dependent on HTTP path - **[endpoint](examples/endpoint/)**: a simple JSON REST API example featuring diff --git a/build.zig b/build.zig index 5f54516..fb7f6be 100644 --- a/build.zig +++ b/build.zig @@ -54,6 +54,7 @@ pub fn build(b: *std.build.Builder) !void { .{ .name = "cookies", .src = "examples/cookies/cookies.zig" }, .{ .name = "websockets", .src = "examples/websockets/websockets.zig" }, .{ .name = "userpass_session", .src = "examples/userpass_session_auth/userpass_session_auth.zig" }, + .{ .name = "sendfile", .src = "examples/sendfile/sendfile.zig" }, }) |excfg| { const ex_name = excfg.name; const ex_src = excfg.src; @@ -148,10 +149,6 @@ pub fn build(b: *std.build.Builder) !void { sendfile_tests.linkLibrary(facil_dep.artifact("facil.io")); sendfile_tests.addModule("zap", zap_module); const run_sendfile_tests = b.addRunArtifact(sendfile_tests); - // TODO: for some reason, tests aren't run more than once unless - // dependencies have changed. - // So, for now, we just force the exe to be built, so in order that - // we can call it again when needed. const install_sendfile_tests = b.addInstallArtifact(sendfile_tests); // test commands diff --git a/examples/sendfile/sendfile.zig b/examples/sendfile/sendfile.zig new file mode 100644 index 0000000..2fbb448 --- /dev/null +++ b/examples/sendfile/sendfile.zig @@ -0,0 +1,46 @@ +const std = @import("std"); +const zap = @import("zap"); + +var buffer: [1024]u8 = undefined; +var read_len: ?usize = null; + +const testfile = @embedFile("testfile.txt"); + +pub fn on_request(r: zap.SimpleRequest) void { + // Sends a file if present in the filesystem orelse returns an error. + // + // - efficiently sends a file using gzip compression + // - also handles range requests if `Range` or `If-Range` headers are present in the request. + // - sends the response headers and the specified file (the response's body). + // + // On success, the `r.h` handle will be consumed and invalid. + // On error, the handle will still be valid and should be used to send an error response + // + // Important: sets last-modified and cache-control headers with a max-age value of 1 hour! + if (r.sendFile("examples/sendfile/testfile.txt")) {} else |err| { + std.log.err("Unable to send file: {any}", .{err}); + } +} + +pub fn main() !void { + // setup listener + var listener = zap.SimpleHttpListener.init( + .{ + .port = 3000, + .on_request = on_request, + .log = true, + .max_clients = 10, + .max_body_size = 1 * 1024, // careful here + }, + ); + + zap.enableDebugLog(); + try listener.listen(); + + std.debug.print("Visit me on http://127.0.0.1:3000\n", .{}); + + zap.start(.{ + .threads = 1, + .workers = 0, + }); +} diff --git a/examples/sendfile/testfile.txt b/examples/sendfile/testfile.txt new file mode 100644 index 0000000..e0927a6 --- /dev/null +++ b/examples/sendfile/testfile.txt @@ -0,0 +1 @@ +All your codebase are belong to us! diff --git a/src/tests/test_sendfile.zig b/src/tests/test_sendfile.zig index 2bad45c..31af22c 100644 --- a/src/tests/test_sendfile.zig +++ b/src/tests/test_sendfile.zig @@ -38,7 +38,7 @@ test "send file" { // setup listener var listener = zap.SimpleHttpListener.init( .{ - .port = 3001, + .port = 3002, .on_request = on_request, .log = false, .max_clients = 10, @@ -48,7 +48,7 @@ test "send file" { zap.enableDebugLog(); try listener.listen(); - const thread = try makeRequestThread(allocator, "http://127.0.0.1:3001/?file=src/tests/testfile.txt"); + const thread = try makeRequestThread(allocator, "http://127.0.0.1:3002/?file=src/tests/testfile.txt"); defer thread.join(); zap.start(.{ .threads = 1, diff --git a/targets.txt b/targets.txt index 6958208..56c61f8 100644 --- a/targets.txt +++ b/targets.txt @@ -12,4 +12,5 @@ pkghash cookies websockets userpass_session +sendfile