1
0
Fork 0
mirror of https://github.com/zigzap/zap.git synced 2025-10-21 07:34:08 +00:00

Merge branch 'zig-0.12.0'

This commit is contained in:
Rene Schallner 2024-04-21 14:20:15 +02:00
commit 1e1999802a
38 changed files with 426 additions and 267 deletions

View file

@ -1,21 +1,20 @@
name: Works with Zig master name: Works with Zig master
on: on:
# push: push:
# branches: branches:
# - master - zig-0.12.0
# pull_request: pull_request:
# branches: branches:
# - master - zig-0.12.0
# schedule: schedule:
# - cron: "0 0 * * *" - cron: "0 0 * * *"
workflow_dispatch: workflow_dispatch:
jobs: jobs:
ci: ci:
strategy: strategy:
matrix: matrix:
# platform: [ubuntu-latest, windows-latest, macos-latest] platform: [ubuntu-latest, macos-latest]
platform: [ubuntu-latest]
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -26,5 +25,46 @@ jobs:
run: zig version run: zig version
- name: Build all examples - name: Build all examples
run: zig build all run: zig build all
- name: Run all tests # Run tests separately so we can see more clearly which one fails
run: zig build test - name: Run mustache tests
run: zig build test-mustache
- name: Run httpparams tests
run: zig build test-httpparams
- name: Run sendfile tests
run: zig build test-sendfile
- name: Run authentication tests
run: zig build test-authentication
- name: Report end of tests
run: echo "tests finished"
update-readme:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
steps:
- uses: actions/checkout@v3
- uses: goto-bus-stop/setup-zig@v2
with:
version: master
- name: Build announceybot
run: zig build announceybot
- name: Run script to update README
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ steps.tag.outputs.version }}
run: |
zig-out/bin/announceybot update-readme "zig-0.12.0"
- name: Commit and push if it has changed
run: |
git diff
git checkout zig-0.12.0
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git commit -am "Update README"
git push origin zig-0.12.0
>>>>>>> zig-0.12.0

1
.gitignore vendored
View file

@ -11,7 +11,6 @@ wrk/csharp/obj/
wrk/csharp/out/ wrk/csharp/out/
scratch scratch
**/.mypy_cache/* **/.mypy_cache/*
docs/
.DS_Store .DS_Store
.vs/ .vs/
**/*.perflog **/*.perflog

View file

@ -1,5 +1,3 @@
# ⚡zap⚡ - blazingly fast backends in zig # ⚡zap⚡ - blazingly fast backends in zig
![](https://github.com/zigzap/zap/actions/workflows/build-zig-11.yml/badge.svg) ![](https://github.com/zigzap/zap/actions/workflows/mastercheck.yml/badge.svg) [![Discord](https://img.shields.io/discord/1107835896356675706?label=chat&logo=discord&style=plastic)](https://discord.gg/jQAAN6Ubyj) ![](https://github.com/zigzap/zap/actions/workflows/build-zig-11.yml/badge.svg) ![](https://github.com/zigzap/zap/actions/workflows/mastercheck.yml/badge.svg) [![Discord](https://img.shields.io/discord/1107835896356675706?label=chat&logo=discord&style=plastic)](https://discord.gg/jQAAN6Ubyj)
@ -26,17 +24,17 @@ that it proved to be:
Exactly the goals I set out to achieve! Exactly the goals I set out to achieve!
## Most FAQ: ## Most FAQ:
### Zap uses the latest stable zig release (0.11.0) for a reason. So you don't have to keep up with frequent breaking changes. It's an "LTS feature". If you want to use zig master, use the `zig-0.12.0` branch but be aware that I don't provide `build.zig.zon` snippets or tagged releases for it for the time being. If you know what you are doing, that shouldn't stop you from using it with zig master though. ### Zap uses the latest stable zig release (0.1@.0) for a reason. So you don't have to keep up with frequent breaking changes. It's an "LTS feature". If you want to use zig master, use the `zig-0.13.0` branch (coming soon) but be aware that I don't provide `build.zig.zon` snippets or tagged releases for it for the time being. If you know what you are doing, that shouldn't stop you from using it with zig master though.
- Q: **Where is the API documentation?** - Q: **Where is the API documentation?**
- A: Docs are a work in progress. You can check them out [here](https://zigzap.org/zap). The docs are based on the `zig-0.12.0` branch but apply to the current release (zig 0.11.0), too. - A: Docs are a work in progress. You can check them out [here](https://zigzap.org/zap).
- A: Run `zig build run-docserver` to serve them locally.
- Q: **Zap doesn't build with Zig master?** - Q: **Zap doesn't build with Zig master?**
- A: See the 0.12.0 branch. An example of how to use it is - A: See the 0.13.0 branch (soon). An example of how to use it is
[here](https://github.com/zigzap/hello-0.12.0). Please note that the 0.12.0 [here](https://github.com/zigzap/hello-0.13.0). Please note that the 0.13.0
branch is not the official master branch of ZAP. Yet. Until zig 0.12.0 is branch is not the official master branch of ZAP. Yet. Until zig 0.13.0 is
released. released.
- Q: **Does ZAP work on Windows?** - Q: **Does ZAP work on Windows?**
- A: No. This is due to the underlying facil.io C library. Future versions of - A: No. This is due to the underlying facil.io C library. Future versions of
@ -57,6 +55,10 @@ I recommend checking out **Endpoint-based examples for more realistic
use cases**. Most of the examples are super stripped down to only include use cases**. Most of the examples are super stripped down to only include
what's necessary to show a feature. what's necessary to show a feature.
**NOTE: To see API docs, run `zig build run-docserver`.** To specify a custom
port and docs dir: `zig build docserver && zig-out/bin/docserver --port=8989
--docs=path/to/docs`.
- **Super easy build process**: Zap's `build.zig` now uses the new Zig package - **Super easy build process**: Zap's `build.zig` now uses the new Zig package
manager for its C-dependencies, no git submodules anymore. manager for its C-dependencies, no git submodules anymore.
- _tested on Linux and macOS (arm, M1)_ - _tested on Linux and macOS (arm, M1)_
@ -222,7 +224,7 @@ code leaks memory.
## Getting started ## Getting started
Make sure you have **the latest zig release (0.11.0)** installed. Fetch it from Make sure you have zig 0.12.0 installed. Fetch it from
[here](https://ziglang.org/download). [here](https://ziglang.org/download).
```shell ```shell
@ -236,7 +238,7 @@ $ # open http://localhost:3000 in your browser
## Using ⚡zap⚡ in your own projects ## Using ⚡zap⚡ in your own projects
Make sure you have **the latest zig release (0.11.0)** installed. Fetch it from Make sure you have **the latest zig release (0.12.0)** installed. Fetch it from
[here](https://ziglang.org/download). [here](https://ziglang.org/download).
If you don't have an existing zig project, create one like this: If you don't have an existing zig project, create one like this:
@ -250,7 +252,7 @@ $ git init ## (optional)
`nix develop` to get a development shell providing zig and all `nix develop` to get a development shell providing zig and all
dependencies to build and run the GO, python, and rust examples for the dependencies to build and run the GO, python, and rust examples for the
`wrk` performance tests. For the mere building of zap projects, `wrk` performance tests. For the mere building of zap projects,
`nix develop .#build` will only fetch zig 0.11.0. `nix develop .#build` will only fetch zig 0.11.0. TODO: upgrade to zig 0.12.
With an existing Zig project, adding Zap to it is easy: With an existing Zig project, adding Zap to it is easy:
@ -268,9 +270,14 @@ To add zap to `build.zig.zon`:
.dependencies = .{ .dependencies = .{
// zap v0.6.0 // zap v0.6.0
.zap = .{ .zap = .{
.url = "https://github.com/zigzap/zap/archive/refs/tags/v0.6.0.tar.gz", // when tagged:
.hash = "1220a5a1e6b18fa384d8a98e5d5a25720ddadbcfed01da2e4ca55c7cfb3dc1caa62a", // .url = "https://github.com/zigzap/zap/archive/refs/tags/zig-0.12.0.tar.gz",
} .url = "https://github.com/zigzap/zap/archive/zig-0.12.0.tar.gz",
.hash = "122002bc4a3fb6d4c465ce9f7f0af06e9ffbe38a6ed8c7375a2121d05eee294af893",
},
.paths = .{
"",
},
} }
} }
``` ```
@ -285,7 +292,8 @@ Then, in your `build.zig`'s `build` function, add the following before
.optimize = optimize, .optimize = optimize,
.openssl = false, // set to true to enable TLS support .openssl = false, // set to true to enable TLS support
}); });
exe.addModule("zap", zap.module("zap"));
exe.root_module.addImport("zap", zap.module("zap"));
exe.linkLibrary(zap.artifact("facil.io")); exe.linkLibrary(zap.artifact("facil.io"));
``` ```
@ -404,28 +412,3 @@ pub fn main() !void {
}); });
} }
``` ```

View file

@ -1,11 +1,11 @@
const std = @import("std"); const std = @import("std");
const build_facilio = @import("facil.io/build.zig").build_facilio; const build_facilio = @import("facil.io/build.zig").build_facilio;
pub fn build(b: *std.build.Builder) !void { pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{}); const target = b.standardTargetOptions(.{});
if (target.getOsTag() == .windows) { if (target.result.os.tag == .windows) {
std.log.err("\x1b[31mPlatform Not Supported\x1b[0m\nCurrently, Facil.io and Zap are not compatible with Windows. Consider using Linux or Windows Subsystem for Linux (WSL) instead.\nFor more information, please see:\n- https://github.com/zigzap/zap#most-faq\n- https://facil.io/#forking-contributing-and-all-that-jazz\n", .{}); std.log.err("\x1b[31mPlatform Not Supported\x1b[0m\nCurrently, Facil.io and Zap are not compatible with Windows. Consider using Linux or Windows Subsystem for Linux (WSL) instead.\nFor more information, please see:\n- https://github.com/zigzap/zap#most-faq\n- https://facil.io/#forking-contributing-and-all-that-jazz\n", .{});
std.os.exit(1); std.process.exit(1);
} }
// Standard release options allow the person running `zig build` to select // Standard release options allow the person running `zig build` to select
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall.
@ -13,24 +13,39 @@ pub fn build(b: *std.build.Builder) !void {
const use_openssl = b.option(bool, "openssl", "Use system-installed openssl for TLS support in zap") orelse blk: { const use_openssl = b.option(bool, "openssl", "Use system-installed openssl for TLS support in zap") orelse blk: {
// Alternatively, use an os env var to determine whether to build openssl support // Alternatively, use an os env var to determine whether to build openssl support
if (std.os.getenv("ZAP_USE_OPENSSL")) |val| { if (std.posix.getenv("ZAP_USE_OPENSSL")) |val| {
if (std.mem.eql(u8, val, "true")) break :blk true; if (std.mem.eql(u8, val, "true")) break :blk true;
} }
break :blk false; break :blk false;
}; };
// create a module to be used internally. // create a module to be used internally.
var zap_module = b.createModule(.{ const zap_module = b.addModule("zap", .{
.source_file = .{ .path = "src/zap.zig" }, .root_source_file = .{ .path = "src/zap.zig" },
}); });
// register the module so it can be referenced using the package manager. // register the module so it can be referenced using the package manager.
try b.modules.put(b.dupe("zap"), zap_module); // try b.modules.put(b.dupe("zap"), zap_module);
const facilio = try build_facilio("facil.io", b, target, optimize, use_openssl); const facilio = try build_facilio("facil.io", b, target, optimize, use_openssl);
const all_step = b.step("all", "build all examples"); const all_step = b.step("all", "build all examples");
// -- Docs
const docs_obj = b.addObject(.{
.name = "zap", // name doesn't seem to matter
.root_source_file = .{ .path = "src/zap.zig" },
.target = target,
.optimize = .Debug,
});
const install_docs = b.addInstallDirectory(.{
.install_dir = .prefix,
.install_subdir = "zap", // will also be the main namespace in the docs
.source_dir = docs_obj.getEmittedDocs(),
});
b.step("docs", "Build docs").dependOn(&install_docs.step);
// --
inline for ([_]struct { inline for ([_]struct {
name: []const u8, name: []const u8,
src: []const u8, src: []const u8,
@ -85,8 +100,8 @@ pub fn build(b: *std.build.Builder) !void {
.optimize = optimize, .optimize = optimize,
}); });
example.root_module.addImport("zap", zap_module);
example.linkLibrary(facilio); example.linkLibrary(facilio);
example.addModule("zap", zap_module);
// const example_run = example.run(); // const example_run = example.run();
const example_run = b.addRunArtifact(example); const example_run = b.addRunArtifact(example);
@ -125,7 +140,7 @@ pub fn build(b: *std.build.Builder) !void {
.optimize = optimize, .optimize = optimize,
}); });
auth_tests.linkLibrary(facilio); auth_tests.linkLibrary(facilio);
auth_tests.addModule("zap", zap_module); auth_tests.root_module.addImport("zap", zap_module);
const run_auth_tests = b.addRunArtifact(auth_tests); const run_auth_tests = b.addRunArtifact(auth_tests);
const install_auth_tests = b.addInstallArtifact(auth_tests, .{}); const install_auth_tests = b.addInstallArtifact(auth_tests, .{});
@ -138,7 +153,7 @@ pub fn build(b: *std.build.Builder) !void {
.optimize = optimize, .optimize = optimize,
}); });
mustache_tests.linkLibrary(facilio); mustache_tests.linkLibrary(facilio);
mustache_tests.addModule("zap", zap_module); mustache_tests.root_module.addImport("zap", zap_module);
const run_mustache_tests = b.addRunArtifact(mustache_tests); const run_mustache_tests = b.addRunArtifact(mustache_tests);
const install_mustache_tests = b.addInstallArtifact(mustache_tests, .{}); const install_mustache_tests = b.addInstallArtifact(mustache_tests, .{});
@ -152,7 +167,8 @@ pub fn build(b: *std.build.Builder) !void {
}); });
httpparams_tests.linkLibrary(facilio); httpparams_tests.linkLibrary(facilio);
httpparams_tests.addModule("zap", zap_module); httpparams_tests.root_module.addImport("zap", zap_module);
const run_httpparams_tests = b.addRunArtifact(httpparams_tests); const run_httpparams_tests = b.addRunArtifact(httpparams_tests);
// TODO: for some reason, tests aren't run more than once unless // TODO: for some reason, tests aren't run more than once unless
// dependencies have changed. // dependencies have changed.
@ -169,7 +185,7 @@ pub fn build(b: *std.build.Builder) !void {
}); });
sendfile_tests.linkLibrary(facilio); sendfile_tests.linkLibrary(facilio);
sendfile_tests.addModule("zap", zap_module); sendfile_tests.root_module.addImport("zap", zap_module);
const run_sendfile_tests = b.addRunArtifact(sendfile_tests); const run_sendfile_tests = b.addRunArtifact(sendfile_tests);
const install_sendfile_tests = b.addInstallArtifact(sendfile_tests, .{}); const install_sendfile_tests = b.addInstallArtifact(sendfile_tests, .{});
@ -202,7 +218,7 @@ pub fn build(b: *std.build.Builder) !void {
// //
// pkghash // pkghash
// //
var pkghash_exe = b.addExecutable(.{ const pkghash_exe = b.addExecutable(.{
.name = "pkghash", .name = "pkghash",
.root_source_file = .{ .path = "./tools/pkghash.zig" }, .root_source_file = .{ .path = "./tools/pkghash.zig" },
.target = target, .target = target,
@ -213,10 +229,33 @@ pub fn build(b: *std.build.Builder) !void {
pkghash_step.dependOn(&pkghash_build_step.step); pkghash_step.dependOn(&pkghash_build_step.step);
all_step.dependOn(&pkghash_build_step.step); all_step.dependOn(&pkghash_build_step.step);
//
// docserver
//
const docserver_exe = b.addExecutable(.{
.name = "docserver",
.root_source_file = .{ .path = "./tools/docserver.zig" },
.target = target,
.optimize = optimize,
});
docserver_exe.linkLibrary(facilio);
docserver_exe.root_module.addImport("zap", zap_module);
var docserver_step = b.step("docserver", "Build docserver");
const docserver_build_step = b.addInstallArtifact(docserver_exe, .{});
docserver_step.dependOn(&docserver_build_step.step);
docserver_step.dependOn(&install_docs.step);
const docserver_run_step = b.step("run-docserver", "run the docserver");
const docserver_run = b.addRunArtifact(docserver_exe);
docserver_run_step.dependOn(&docserver_run.step);
docserver_run_step.dependOn(docserver_step);
all_step.dependOn(&docserver_build_step.step);
// //
// announceybot // announceybot
// //
var announceybot_exe = b.addExecutable(.{ const announceybot_exe = b.addExecutable(.{
.name = "announceybot", .name = "announceybot",
.root_source_file = .{ .path = "./tools/announceybot.zig" }, .root_source_file = .{ .path = "./tools/announceybot.zig" },
.target = target, .target = target,

View file

@ -1 +1,10 @@
.{ .name = "zap", .version = "0.6.0" } .{
.name = "zap",
.version = "0.7.0",
.paths = .{
"build.zig",
"build.zig.zon",
"src",
"facil.io",
},
}

View file

@ -22,7 +22,10 @@ Here is a complete `build.zig.zon` example:
.zap = .{ .zap = .{
.url = "https://github.com/zigzap/zap/archive/refs/tags/{tag}.tar.gz", .url = "https://github.com/zigzap/zap/archive/refs/tags/{tag}.tar.gz",
.hash = "{hash}", .hash = "{hash}",
} },
.paths = .{
"",
},
} }
} }
@ -35,7 +38,8 @@ Then, in your `build.zig`'s `build` function, add the following before
const zap = b.dependency("zap", .{ const zap = b.dependency("zap", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
.openssl = false, // set to true to enable TLS support
}); });
exe.addModule("zap", zap.module("zap")); exe.root_module.addImport("zap", zap.module("zap"));
exe.linkLibrary(zap.artifact("facil.io")); exe.linkLibrary(zap.artifact("facil.io"));
``` ```

View file

@ -5,7 +5,7 @@ const Handler = struct {
var alloc: std.mem.Allocator = undefined; var alloc: std.mem.Allocator = undefined;
pub fn on_request(r: zap.Request) void { pub fn on_request(r: zap.Request) void {
// check for FORM parameters // parse for FORM (body) parameters first
r.parseBody() catch |err| { r.parseBody() catch |err| {
std.log.err("Parse Body error: {any}. Expected if body is empty", .{err}); std.log.err("Parse Body error: {any}. Expected if body is empty", .{err});
}; };
@ -13,10 +13,11 @@ const Handler = struct {
if (r.body) |body| { if (r.body) |body| {
std.log.info("Body length is {any}\n", .{body.len}); std.log.info("Body length is {any}\n", .{body.len});
} }
// check for query params (for ?terminate=true)
// parse potential query params (for ?terminate=true)
r.parseQuery(); r.parseQuery();
var param_count = r.getParamCount(); const param_count = r.getParamCount();
std.log.info("param_count: {}", .{param_count}); std.log.info("param_count: {}", .{param_count});
// iterate over all params // iterate over all params
@ -56,8 +57,11 @@ const Handler = struct {
else => { else => {
// might be a string param, we don't care // might be a string param, we don't care
// let's just get it as string // let's just get it as string
// always_alloc param = false -> the string will be a slice from the request buffer
// --> no deinit necessary
if (r.getParamStr(Handler.alloc, kv.key.str, false)) |maybe_str| { if (r.getParamStr(Handler.alloc, kv.key.str, false)) |maybe_str| {
const value: []const u8 = if (maybe_str) |s| s.str else "(no value)"; const value: []const u8 = if (maybe_str) |s| s.str else "(no value)";
// above, we didn't defer s.deinit because the string is just a slice from the request buffer
std.log.debug(" {s} = {s}", .{ kv.key.str, value }); std.log.debug(" {s} = {s}", .{ kv.key.str, value });
} else |err| { } else |err| {
std.log.err("Error: {any}\n", .{err}); std.log.err("Error: {any}\n", .{err});
@ -70,7 +74,6 @@ const Handler = struct {
// check if we received a terminate=true parameter // check if we received a terminate=true parameter
if (r.getParamStr(Handler.alloc, "terminate", false)) |maybe_str| { if (r.getParamStr(Handler.alloc, "terminate", false)) |maybe_str| {
if (maybe_str) |*s| { if (maybe_str) |*s| {
defer s.deinit();
std.log.info("?terminate={s}\n", .{s.str}); std.log.info("?terminate={s}\n", .{s.str});
if (std.mem.eql(u8, s.str, "true")) { if (std.mem.eql(u8, s.str, "true")) {
zap.stop(); zap.stop();
@ -87,7 +90,7 @@ pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true, .thread_safe = true,
}){}; }){};
var allocator = gpa.allocator(); const allocator = gpa.allocator();
Handler.alloc = allocator; Handler.alloc = allocator;

View file

@ -5,17 +5,19 @@ const zap = @import("zap");
fn makeRequest(a: std.mem.Allocator, url: []const u8) !void { fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
const uri = try std.Uri.parse(url); const uri = try std.Uri.parse(url);
var h = std.http.Headers{ .allocator = a };
defer h.deinit();
var http_client: std.http.Client = .{ .allocator = a }; var http_client: std.http.Client = .{ .allocator = a };
defer http_client.deinit(); defer http_client.deinit();
var req = try http_client.request(.GET, uri, h, .{}); var server_header_buffer: [2048]u8 = undefined;
var req = try http_client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
.extra_headers = &.{
.{ .name = "cookie", .value = "ZIG_ZAP=awesome" },
},
});
defer req.deinit(); defer req.deinit();
try req.headers.append("cookie", "ZIG_ZAP=awesome"); try req.send();
try req.start();
try req.wait(); try req.wait();
} }
@ -28,7 +30,7 @@ pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true, .thread_safe = true,
}){}; }){};
var allocator = gpa.allocator(); const allocator = gpa.allocator();
const Handler = struct { const Handler = struct {
var alloc: std.mem.Allocator = undefined; var alloc: std.mem.Allocator = undefined;
@ -37,17 +39,19 @@ pub fn main() !void {
std.debug.print("\n=====================================================\n", .{}); std.debug.print("\n=====================================================\n", .{});
defer std.debug.print("=====================================================\n\n", .{}); defer std.debug.print("=====================================================\n\n", .{});
r.parseCookies(false); r.parseCookies(false); // url_encoded = false
var cookie_count = r.getCookiesCount(); const cookie_count = r.getCookiesCount();
std.log.info("cookie_count: {}", .{cookie_count}); std.log.info("cookie_count: {}", .{cookie_count});
// iterate over all cookies as strings // iterate over all cookies as strings (always_alloc=false)
var strCookies = r.cookiesToOwnedStrList(alloc, false) catch unreachable; var strCookies = r.cookiesToOwnedStrList(alloc, false) catch unreachable;
defer strCookies.deinit(); defer strCookies.deinit();
std.debug.print("\n", .{}); std.debug.print("\n", .{});
for (strCookies.items) |kv| { for (strCookies.items) |kv| {
std.log.info("CookieStr `{s}` is `{s}`", .{ kv.key.str, kv.value.str }); std.log.info("CookieStr `{s}` is `{s}`", .{ kv.key.str, kv.value.str });
// 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", .{}); std.debug.print("\n", .{});
@ -63,7 +67,7 @@ pub fn main() !void {
std.debug.print("\n", .{}); std.debug.print("\n", .{});
if (r.getCookieStr(alloc, "ZIG_ZAP", false)) |maybe_str| { if (r.getCookieStr(alloc, "ZIG_ZAP", false)) |maybe_str| {
if (maybe_str) |*s| { if (maybe_str) |*s| {
defer s.deinit(); defer s.deinit(); // unnecessary because always_alloc=false
std.log.info("Cookie ZIG_ZAP = {s}", .{s.str}); std.log.info("Cookie ZIG_ZAP = {s}", .{s.str});
} else { } else {

View file

@ -3,7 +3,7 @@ const zap = @import("zap");
const UserWeb = @import("userweb.zig"); const UserWeb = @import("userweb.zig");
const StopEndpoint = @import("stopendpoint.zig"); const StopEndpoint = @import("stopendpoint.zig");
// this is just to demo that we can catch arbitrary slugs // this is just to demo that we can catch arbitrary slugs as fallback
fn on_request(r: zap.Request) void { fn on_request(r: zap.Request) void {
if (r.path) |the_path| { if (r.path) |the_path| {
std.debug.print("REQUESTED PATH: {s}\n", .{the_path}); std.debug.print("REQUESTED PATH: {s}\n", .{the_path});
@ -16,7 +16,7 @@ pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true, .thread_safe = true,
}){}; }){};
var allocator = gpa.allocator(); const allocator = gpa.allocator();
// we scope everything that can allocate within this block for leak detection // we scope everything that can allocate within this block for leak detection
{ {
@ -56,7 +56,7 @@ pub fn main() !void {
// and run // and run
zap.start(.{ zap.start(.{
.threads = 2000, .threads = 2,
// IMPORTANT! It is crucial to only have a single worker for this example to work! // IMPORTANT! It is crucial to only have a single worker for this example to work!
// Multiple workers would have multiple copies of the users hashmap. // Multiple workers would have multiple copies of the users hashmap.
// //

View file

@ -41,12 +41,12 @@ pub fn addByName(self: *Self, first: ?[]const u8, last: ?[]const u8) !usize {
user.lastnamelen = 0; user.lastnamelen = 0;
if (first) |firstname| { if (first) |firstname| {
std.mem.copy(u8, user.firstnamebuf[0..], firstname); @memcpy(user.firstnamebuf[0..firstname.len], firstname);
user.firstnamelen = firstname.len; user.firstnamelen = firstname.len;
} }
if (last) |lastname| { if (last) |lastname| {
std.mem.copy(u8, user.lastnamebuf[0..], lastname); @memcpy(user.lastnamebuf[0..lastname.len], lastname);
user.lastnamelen = lastname.len; user.lastnamelen = lastname.len;
} }
@ -101,11 +101,11 @@ pub fn update(
pUser.firstnamelen = 0; pUser.firstnamelen = 0;
pUser.lastnamelen = 0; pUser.lastnamelen = 0;
if (first) |firstname| { if (first) |firstname| {
std.mem.copy(u8, pUser.firstnamebuf[0..], firstname); @memcpy(pUser.firstnamebuf[0..firstname.len], firstname);
pUser.firstnamelen = firstname.len; pUser.firstnamelen = firstname.len;
} }
if (last) |lastname| { if (last) |lastname| {
std.mem.copy(u8, pUser.lastnamebuf[0..], lastname); @memcpy(pUser.lastnamebuf[0..lastname.len], lastname);
pUser.lastnamelen = lastname.len; pUser.lastnamelen = lastname.len;
} }
} }

View file

@ -54,7 +54,8 @@ fn userIdFromPath(self: *Self, path: []const u8) ?usize {
} }
fn getUser(e: *zap.Endpoint, r: zap.Request) void { fn getUser(e: *zap.Endpoint, r: zap.Request) void {
const self = @fieldParentPtr(Self, "ep", e); const self: *Self = @fieldParentPtr("ep", e);
if (r.path) |path| { if (r.path) |path| {
// /users // /users
if (path.len == e.settings.path.len) { if (path.len == e.settings.path.len) {
@ -81,9 +82,9 @@ fn listUsers(self: *Self, r: zap.Request) void {
} }
fn postUser(e: *zap.Endpoint, r: zap.Request) void { fn postUser(e: *zap.Endpoint, r: zap.Request) void {
const self = @fieldParentPtr(Self, "ep", e); const self: *Self = @fieldParentPtr("ep", e);
if (r.body) |body| { if (r.body) |body| {
var maybe_user: ?std.json.Parsed(User) = std.json.parseFromSlice(User, self.alloc, body, .{}) catch null; const maybe_user: ?std.json.Parsed(User) = std.json.parseFromSlice(User, self.alloc, body, .{}) catch null;
if (maybe_user) |u| { if (maybe_user) |u| {
defer u.deinit(); defer u.deinit();
if (self._users.addByName(u.value.first_name, u.value.last_name)) |id| { if (self._users.addByName(u.value.first_name, u.value.last_name)) |id| {
@ -100,12 +101,12 @@ fn postUser(e: *zap.Endpoint, r: zap.Request) void {
} }
fn putUser(e: *zap.Endpoint, r: zap.Request) void { fn putUser(e: *zap.Endpoint, r: zap.Request) void {
const self = @fieldParentPtr(Self, "ep", e); const self: *Self = @fieldParentPtr("ep", e);
if (r.path) |path| { if (r.path) |path| {
if (self.userIdFromPath(path)) |id| { if (self.userIdFromPath(path)) |id| {
if (self._users.get(id)) |_| { if (self._users.get(id)) |_| {
if (r.body) |body| { if (r.body) |body| {
var maybe_user: ?std.json.Parsed(User) = std.json.parseFromSlice(User, self.alloc, body, .{}) catch null; const maybe_user: ?std.json.Parsed(User) = std.json.parseFromSlice(User, self.alloc, body, .{}) catch null;
if (maybe_user) |u| { if (maybe_user) |u| {
defer u.deinit(); defer u.deinit();
var jsonbuf: [128]u8 = undefined; var jsonbuf: [128]u8 = undefined;
@ -126,7 +127,7 @@ fn putUser(e: *zap.Endpoint, r: zap.Request) void {
} }
fn deleteUser(e: *zap.Endpoint, r: zap.Request) void { fn deleteUser(e: *zap.Endpoint, r: zap.Request) void {
const self = @fieldParentPtr(Self, "ep", e); const self: *Self = @fieldParentPtr("ep", e);
if (r.path) |path| { if (r.path) |path| {
if (self.userIdFromPath(path)) |id| { if (self.userIdFromPath(path)) |id| {
var jsonbuf: [128]u8 = undefined; var jsonbuf: [128]u8 = undefined;

View file

@ -41,7 +41,7 @@ fn setupUserData(a: std.mem.Allocator) !void {
} }
pub fn main() !void { pub fn main() !void {
var a = std.heap.page_allocator; const a = std.heap.page_allocator;
try setupUserData(a); try setupUserData(a);
var listener = zap.HttpListener.init(.{ var listener = zap.HttpListener.init(.{
.port = 3000, .port = 3000,

View file

@ -5,16 +5,16 @@ const zap = @import("zap");
fn makeRequest(a: std.mem.Allocator, url: []const u8) !void { fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
const uri = try std.Uri.parse(url); const uri = try std.Uri.parse(url);
var h = std.http.Headers{ .allocator = a };
defer h.deinit();
var http_client: std.http.Client = .{ .allocator = a }; var http_client: std.http.Client = .{ .allocator = a };
defer http_client.deinit(); defer http_client.deinit();
var req = try http_client.request(.GET, uri, h, .{}); var server_header_buffer: [2048]u8 = undefined;
var req = try http_client.open(.GET, uri, .{
.server_header_buffer = &server_header_buffer,
});
defer req.deinit(); defer req.deinit();
try req.start(); try req.send();
try req.wait(); try req.wait();
} }
@ -27,7 +27,7 @@ pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true, .thread_safe = true,
}){}; }){};
var allocator = gpa.allocator(); const allocator = gpa.allocator();
const Handler = struct { const Handler = struct {
var alloc: std.mem.Allocator = undefined; var alloc: std.mem.Allocator = undefined;
@ -44,7 +44,7 @@ pub fn main() !void {
// check for query parameters // check for query parameters
r.parseQuery(); r.parseQuery();
var param_count = r.getParamCount(); const param_count = r.getParamCount();
std.log.info("param_count: {}", .{param_count}); std.log.info("param_count: {}", .{param_count});
// ================================================================ // ================================================================

View file

@ -30,7 +30,7 @@ fn help_and_exit(filename: []const u8, err: anyerror) void {
, ,
.{ filename, err }, .{ filename, err },
); );
std.os.exit(1); std.process.exit(1);
} }
pub fn main() !void { pub fn main() !void {
const CERT_FILE = "mycert.pem"; const CERT_FILE = "mycert.pem";

View file

@ -72,7 +72,7 @@ const UserMiddleWare = struct {
pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool {
// this is how we would get our self pointer // this is how we would get our self pointer
var self = @fieldParentPtr(Self, "handler", handler); const self: *Self = @fieldParentPtr("handler", handler);
_ = self; _ = self;
// do our work: fill in the user field of the context // do our work: fill in the user field of the context
@ -115,7 +115,7 @@ const SessionMiddleWare = struct {
// note that the first parameter is of type *Handler, not *Self !!! // note that the first parameter is of type *Handler, not *Self !!!
pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool {
// this is how we would get our self pointer // this is how we would get our self pointer
var self = @fieldParentPtr(Self, "handler", handler); const self: *Self = @fieldParentPtr("handler", handler);
_ = self; _ = self;
context.session = Session{ context.session = Session{
@ -151,7 +151,7 @@ const HtmlMiddleWare = struct {
pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool {
// this is how we would get our self pointer // this is how we would get our self pointer
var self = @fieldParentPtr(Self, "handler", handler); const self: *Self = @fieldParentPtr("handler", handler);
_ = self; _ = self;
std.debug.print("\n\nHtmlMiddleware: handling request with context: {any}\n\n", .{context}); std.debug.print("\n\nHtmlMiddleware: handling request with context: {any}\n\n", .{context});
@ -190,7 +190,7 @@ pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true, .thread_safe = true,
}){}; }){};
var allocator = gpa.allocator(); const allocator = gpa.allocator();
SharedAllocator.init(allocator); SharedAllocator.init(allocator);
// we create our HTML middleware component that handles the request // we create our HTML middleware component that handles the request

View file

@ -60,7 +60,7 @@ const UserMiddleWare = struct {
pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool {
// this is how we would get our self pointer // this is how we would get our self pointer
var self = @fieldParentPtr(Self, "handler", handler); const self: *Self = @fieldParentPtr("handler", handler);
_ = self; _ = self;
// do our work: fill in the user field of the context // do our work: fill in the user field of the context
@ -105,7 +105,7 @@ const SessionMiddleWare = struct {
// note that the first parameter is of type *Handler, not *Self !!! // note that the first parameter is of type *Handler, not *Self !!!
pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool { pub fn onRequest(handler: *Handler, r: zap.Request, context: *Context) bool {
// this is how we would get our self pointer // this is how we would get our self pointer
var self = @fieldParentPtr(Self, "handler", handler); const self: *Self = @fieldParentPtr("handler", handler);
_ = self; _ = self;
context.session = Session{ context.session = Session{
@ -155,7 +155,7 @@ const HtmlEndpoint = struct {
} }
pub fn get(ep: *zap.Endpoint, r: zap.Request) void { pub fn get(ep: *zap.Endpoint, r: zap.Request) void {
const self = @fieldParentPtr(Self, "ep", ep); const self: *Self = @fieldParentPtr("ep", ep);
_ = self; _ = self;
var buf: [1024]u8 = undefined; var buf: [1024]u8 = undefined;
@ -200,7 +200,7 @@ pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true, .thread_safe = true,
}){}; }){};
var allocator = gpa.allocator(); const allocator = gpa.allocator();
SharedAllocator.init(allocator); SharedAllocator.init(allocator);
// create the endpoint // create the endpoint

View file

@ -73,7 +73,7 @@ pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true, .thread_safe = true,
}){}; }){};
var allocator = gpa.allocator(); const allocator = gpa.allocator();
var simpleRouter = zap.Router.init(allocator, .{ var simpleRouter = zap.Router.init(allocator, .{
.not_found = not_found, .not_found = not_found,

View file

@ -46,8 +46,8 @@ const ContextManager = struct {
self.lock.lock(); self.lock.lock();
defer self.lock.unlock(); defer self.lock.unlock();
var ctx = try self.allocator.create(Context); const ctx = try self.allocator.create(Context);
var userName = try std.fmt.allocPrint( const userName = try std.fmt.allocPrint(
self.allocator, self.allocator,
"{s}{d}", "{s}{d}",
.{ self.usernamePrefix, self.contexts.items.len }, .{ self.usernamePrefix, self.contexts.items.len },
@ -202,7 +202,7 @@ pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true, .thread_safe = true,
}){}; }){};
var allocator = gpa.allocator(); const allocator = gpa.allocator();
GlobalContextManager = ContextManager.init(allocator, "chatroom", "user-"); GlobalContextManager = ContextManager.init(allocator, "chatroom", "user-");
defer GlobalContextManager.deinit(); defer GlobalContextManager.deinit();

View file

@ -2,11 +2,11 @@ const std = @import("std");
pub fn build_facilio( pub fn build_facilio(
comptime subdir: []const u8, comptime subdir: []const u8,
b: *std.build.Builder, b: *std.Build,
target: std.zig.CrossTarget, target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode, optimize: std.builtin.OptimizeMode,
use_openssl: bool, use_openssl: bool,
) !*std.build.CompileStep { ) !*std.Build.Step.Compile {
const lib = b.addStaticLibrary(.{ const lib = b.addStaticLibrary(.{
.name = "facil.io", .name = "facil.io",
.target = target, .target = target,
@ -15,7 +15,7 @@ pub fn build_facilio(
// Generate flags // Generate flags
var flags = std.ArrayList([]const u8).init(std.heap.page_allocator); var flags = std.ArrayList([]const u8).init(std.heap.page_allocator);
if (lib.optimize != .Debug) try flags.append("-Os"); if (optimize != .Debug) try flags.append("-Os");
try flags.append("-Wno-return-type-c-linkage"); try flags.append("-Wno-return-type-c-linkage");
try flags.append("-fno-sanitize=undefined"); try flags.append("-fno-sanitize=undefined");
@ -26,7 +26,7 @@ pub fn build_facilio(
// //
try flags.append("-DFIO_HTTP_EXACT_LOGGING"); try flags.append("-DFIO_HTTP_EXACT_LOGGING");
if (target.getAbi() == .musl) if (target.result.abi == .musl)
try flags.append("-D_LARGEFILE64_SOURCE"); try flags.append("-D_LARGEFILE64_SOURCE");
if (use_openssl) if (use_openssl)
try flags.append("-DHAVE_OPENSSL -DFIO_TLS_FOUND"); try flags.append("-DHAVE_OPENSSL -DFIO_TLS_FOUND");
@ -42,30 +42,36 @@ pub fn build_facilio(
lib.addIncludePath(.{ .path = subdir ++ "/lib/facil/tls" }); lib.addIncludePath(.{ .path = subdir ++ "/lib/facil/tls" });
// C source files // C source files
lib.addCSourceFiles(&.{ lib.addCSourceFiles(.{
subdir ++ "/lib/facil/fio.c", .files = &.{
subdir ++ "/lib/facil/fio_zig.c", subdir ++ "/lib/facil/fio.c",
subdir ++ "/lib/facil/http/http.c", subdir ++ "/lib/facil/fio_zig.c",
subdir ++ "/lib/facil/http/http1.c", subdir ++ "/lib/facil/http/http.c",
subdir ++ "/lib/facil/http/websockets.c", subdir ++ "/lib/facil/http/http1.c",
subdir ++ "/lib/facil/http/http_internal.c", subdir ++ "/lib/facil/http/websockets.c",
subdir ++ "/lib/facil/fiobj/fiobj_numbers.c", subdir ++ "/lib/facil/http/http_internal.c",
subdir ++ "/lib/facil/fiobj/fio_siphash.c", subdir ++ "/lib/facil/fiobj/fiobj_numbers.c",
subdir ++ "/lib/facil/fiobj/fiobj_str.c", subdir ++ "/lib/facil/fiobj/fio_siphash.c",
subdir ++ "/lib/facil/fiobj/fiobj_ary.c", subdir ++ "/lib/facil/fiobj/fiobj_str.c",
subdir ++ "/lib/facil/fiobj/fiobj_data.c", subdir ++ "/lib/facil/fiobj/fiobj_ary.c",
subdir ++ "/lib/facil/fiobj/fiobj_hash.c", subdir ++ "/lib/facil/fiobj/fiobj_data.c",
subdir ++ "/lib/facil/fiobj/fiobj_json.c", subdir ++ "/lib/facil/fiobj/fiobj_hash.c",
subdir ++ "/lib/facil/fiobj/fiobject.c", subdir ++ "/lib/facil/fiobj/fiobj_json.c",
subdir ++ "/lib/facil/fiobj/fiobj_mustache.c", subdir ++ "/lib/facil/fiobj/fiobject.c",
subdir ++ "/lib/facil/cli/fio_cli.c", subdir ++ "/lib/facil/fiobj/fiobj_mustache.c",
}, flags.items); subdir ++ "/lib/facil/cli/fio_cli.c",
},
.flags = flags.items,
});
if (use_openssl) { if (use_openssl) {
lib.addCSourceFiles(&.{ lib.addCSourceFiles(.{
subdir ++ "/lib/facil/tls/fio_tls_openssl.c", .files = &.{
subdir ++ "/lib/facil/tls/fio_tls_missing.c", subdir ++ "/lib/facil/tls/fio_tls_openssl.c",
}, flags.items); subdir ++ "/lib/facil/tls/fio_tls_missing.c",
},
.flags = flags.items,
});
} }
// link against libc // link against libc

View file

@ -2,4 +2,3 @@
.name = "facil.io", .name = "facil.io",
.version = "0.0.12", .version = "0.0.12",
} }

44
flake.lock generated
View file

@ -3,11 +3,11 @@
"flake-compat": { "flake-compat": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1673956053, "lastModified": 1696426674,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -37,11 +37,11 @@
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1689068808, "lastModified": 1701680307,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -55,11 +55,11 @@
"systems": "systems_2" "systems": "systems_2"
}, },
"locked": { "locked": {
"lastModified": 1685518550, "lastModified": 1701680307,
"narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=", "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef", "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -92,11 +92,11 @@
}, },
"locked": { "locked": {
"dir": "contrib", "dir": "contrib",
"lastModified": 1692702614, "lastModified": 1704461694,
"narHash": "sha256-FeY8hAB77tnUTDbK6WYA+DG3Nx5xQrbOC17Cfl3pTm4=", "narHash": "sha256-dQc9Bkh5uf0R4po3NWnCGx+3eqOZR7iSR4jmRvNNm+E=",
"owner": "neovim", "owner": "neovim",
"repo": "neovim", "repo": "neovim",
"rev": "014b87646fc3273a09d6b20ebb648a8eb24a0a98", "rev": "c509f4907bf7405c9c2ae3f7eff76c5d552944cc",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -108,11 +108,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1702882221, "lastModified": 1704290814,
"narHash": "sha256-L/uOrBqkGsa45EvQk4DLq/aR6JeomW+7Mwe0mC/dVUM=", "narHash": "sha256-LWvKHp7kGxk/GEtlrGYV68qIvPHkU9iToomNFGagixU=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "25fef6e30d8ad48f47a8411ccfe986d8baed8a15", "rev": "70bdadeb94ffc8806c0570eb5c2695ad29f0e421",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -124,16 +124,16 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1689088367, "lastModified": 1702350026,
"narHash": "sha256-Y2tl2TlKCWEHrOeM9ivjCLlRAKH3qoPUE/emhZECU14=", "narHash": "sha256-A+GNZFZdfl4JdDphYKBJ5Ef1HOiFsP18vQe9mqjmUis=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "5c9ddb86679c400d6b7360797b8a22167c2053f8", "rev": "9463103069725474698139ab10f17a9d125da859",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "release-23.05", "ref": "nixos-23.05",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@ -184,11 +184,11 @@
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 1692663634, "lastModified": 1704888534,
"narHash": "sha256-wioqr80UOA0tNXaJy4D0i9fFaLG2RoQi5e9Dpd4WojE=", "narHash": "sha256-douEXUiWCVL9NvWKYBc8ydq51qLLUwlBo6lJJoktkGw=",
"owner": "mitchellh", "owner": "mitchellh",
"repo": "zig-overlay", "repo": "zig-overlay",
"rev": "d666e5137fe0c43353c555fb47748813084decab", "rev": "c69295c92a98947295755a9ac2d49a8d447cc04d",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -90,6 +90,7 @@
devShells.build = pkgs.mkShell { devShells.build = pkgs.mkShell {
nativeBuildInputs = with pkgs; [ nativeBuildInputs = with pkgs; [
zigpkgs."0.11.0" zigpkgs."0.11.0"
pkgs.openssl
]; ];
buildInputs = with pkgs; [ buildInputs = with pkgs; [
@ -103,6 +104,28 @@
# once we set SHELL to point to the interactive bash, neovim will # once we set SHELL to point to the interactive bash, neovim will
# launch the correct $SHELL in its :terminal # launch the correct $SHELL in its :terminal
export SHELL=${pkgs.bashInteractive}/bin/bash export SHELL=${pkgs.bashInteractive}/bin/bash
export LD_LIBRARY_PATH=${pkgs.zlib.out}/lib:${pkgs.icu.out}/lib:${pkgs.openssl.out}/lib:$LD_LIBRARY_PATH
'';
};
devShells.masta = pkgs.mkShell {
nativeBuildInputs = with pkgs; [
zigpkgs.master
pkgs.openssl
];
buildInputs = with pkgs; [
# we need a version of bash capable of being interactive
# as opposed to a bash just used for building this flake
# in non-interactive mode
bashInteractive
];
shellHook = ''
# once we set SHELL to point to the interactive bash, neovim will
# launch the correct $SHELL in its :terminal
export SHELL=${pkgs.bashInteractive}/bin/bash
export LD_LIBRARY_PATH=${pkgs.zlib.out}/lib:${pkgs.icu.out}/lib:${pkgs.openssl.out}/lib:$LD_LIBRARY_PATH
''; '';
}; };

View file

@ -112,7 +112,7 @@ pub fn Authenticating(comptime Authenticator: type) type {
/// GET: here, the auth_endpoint will be passed in as endpoint. /// GET: here, the auth_endpoint will be passed in as endpoint.
/// Authenticates GET requests using the Authenticator. /// Authenticates GET requests using the Authenticator.
pub fn get(e: *Endpoint, r: zap.Request) void { pub fn get(e: *Endpoint, r: zap.Request) void {
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); const authEp: *Self = @fieldParentPtr("auth_endpoint", e);
switch (authEp.authenticator.authenticateRequest(&r)) { switch (authEp.authenticator.authenticateRequest(&r)) {
.AuthFailed => { .AuthFailed => {
if (e.settings.unauthorized) |unauthorized| { if (e.settings.unauthorized) |unauthorized| {
@ -132,7 +132,7 @@ pub fn Authenticating(comptime Authenticator: type) type {
/// POST: here, the auth_endpoint will be passed in as endpoint. /// POST: here, the auth_endpoint will be passed in as endpoint.
/// Authenticates POST requests using the Authenticator. /// Authenticates POST requests using the Authenticator.
pub fn post(e: *Endpoint, r: zap.Request) void { pub fn post(e: *Endpoint, r: zap.Request) void {
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); const authEp: *Self = @fieldParentPtr("auth_endpoint", e);
switch (authEp.authenticator.authenticateRequest(&r)) { switch (authEp.authenticator.authenticateRequest(&r)) {
.AuthFailed => { .AuthFailed => {
if (e.settings.unauthorized) |unauthorized| { if (e.settings.unauthorized) |unauthorized| {
@ -152,7 +152,7 @@ pub fn Authenticating(comptime Authenticator: type) type {
/// PUT: here, the auth_endpoint will be passed in as endpoint. /// PUT: here, the auth_endpoint will be passed in as endpoint.
/// Authenticates PUT requests using the Authenticator. /// Authenticates PUT requests using the Authenticator.
pub fn put(e: *Endpoint, r: zap.Request) void { pub fn put(e: *Endpoint, r: zap.Request) void {
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); const authEp: *Self = @fieldParentPtr("auth_endpoint", e);
switch (authEp.authenticator.authenticateRequest(&r)) { switch (authEp.authenticator.authenticateRequest(&r)) {
.AuthFailed => { .AuthFailed => {
if (e.settings.unauthorized) |unauthorized| { if (e.settings.unauthorized) |unauthorized| {
@ -172,7 +172,7 @@ pub fn Authenticating(comptime Authenticator: type) type {
/// DELETE: here, the auth_endpoint will be passed in as endpoint. /// DELETE: here, the auth_endpoint will be passed in as endpoint.
/// Authenticates DELETE requests using the Authenticator. /// Authenticates DELETE requests using the Authenticator.
pub fn delete(e: *Endpoint, r: zap.Request) void { pub fn delete(e: *Endpoint, r: zap.Request) void {
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); const authEp: *Self = @fieldParentPtr("auth_endpoint", e);
switch (authEp.authenticator.authenticateRequest(&r)) { switch (authEp.authenticator.authenticateRequest(&r)) {
.AuthFailed => { .AuthFailed => {
if (e.settings.unauthorized) |unauthorized| { if (e.settings.unauthorized) |unauthorized| {
@ -192,7 +192,7 @@ pub fn Authenticating(comptime Authenticator: type) type {
/// PATCH: here, the auth_endpoint will be passed in as endpoint. /// PATCH: here, the auth_endpoint will be passed in as endpoint.
/// Authenticates PATCH requests using the Authenticator. /// Authenticates PATCH requests using the Authenticator.
pub fn patch(e: *Endpoint, r: zap.Request) void { pub fn patch(e: *Endpoint, r: zap.Request) void {
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); const authEp: *Self = @fieldParentPtr("auth_endpoint", e);
switch (authEp.authenticator.authenticateRequest(&r)) { switch (authEp.authenticator.authenticateRequest(&r)) {
.AuthFailed => { .AuthFailed => {
if (e.settings.unauthorized) |unauthorized| { if (e.settings.unauthorized) |unauthorized| {
@ -212,7 +212,7 @@ pub fn Authenticating(comptime Authenticator: type) type {
/// OPTIONS: here, the auth_endpoint will be passed in as endpoint. /// OPTIONS: here, the auth_endpoint will be passed in as endpoint.
/// Authenticates OPTIONS requests using the Authenticator. /// Authenticates OPTIONS requests using the Authenticator.
pub fn options(e: *Endpoint, r: zap.Request) void { pub fn options(e: *Endpoint, r: zap.Request) void {
const authEp: *Self = @fieldParentPtr(Self, "auth_endpoint", e); const authEp: *Self = @fieldParentPtr("auth_endpoint", e);
switch (authEp.authenticator.authenticateRequest(&r)) { switch (authEp.authenticator.authenticateRequest(&r)) {
.AuthFailed => { .AuthFailed => {
if (e.settings.unauthorized) |unauthorized| { if (e.settings.unauthorized) |unauthorized| {

View file

@ -118,10 +118,10 @@ pub const struct_fio_str_info_s = extern struct {
pub const fio_str_info_s = struct_fio_str_info_s; pub const fio_str_info_s = struct_fio_str_info_s;
pub extern fn http_send_body(h: [*c]http_s, data: ?*anyopaque, length: usize) c_int; pub extern fn http_send_body(h: [*c]http_s, data: ?*anyopaque, length: usize) c_int;
pub fn fiobj_each1(arg_o: FIOBJ, arg_start_at: usize, arg_task: ?*const fn (FIOBJ, ?*anyopaque) callconv(.C) c_int, arg_arg: ?*anyopaque) callconv(.C) usize { pub fn fiobj_each1(arg_o: FIOBJ, arg_start_at: usize, arg_task: ?*const fn (FIOBJ, ?*anyopaque) callconv(.C) c_int, arg_arg: ?*anyopaque) callconv(.C) usize {
var o = arg_o; const o = arg_o;
var start_at = arg_start_at; const start_at = arg_start_at;
var task = arg_task; const task = arg_task;
var arg = arg_arg; const arg = arg_arg;
if ((((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6)))))) and (fiobj_type_vtable(o).*.each != null)) return fiobj_type_vtable(o).*.each.?(o, start_at, task, arg); if ((((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6)))))) and (fiobj_type_vtable(o).*.each != null)) return fiobj_type_vtable(o).*.each.?(o, start_at, task, arg);
return 0; return 0;
} }
@ -288,8 +288,8 @@ pub const fiobj_object_header_s = extern struct {
ref: u32, ref: u32,
}; };
pub fn fiobj_type_is(arg_o: FIOBJ, arg_type: fiobj_type_enum) callconv(.C) usize { pub fn fiobj_type_is(arg_o: FIOBJ, arg_type: fiobj_type_enum) callconv(.C) usize {
var o = arg_o; const o = arg_o;
var @"type" = arg_type; const @"type" = arg_type;
while (true) { while (true) {
switch (@as(c_int, @bitCast(@as(c_uint, @"type")))) { switch (@as(c_int, @bitCast(@as(c_uint, @"type")))) {
@as(c_int, 1) => return @as(usize, @bitCast(@as(c_long, @intFromBool(((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) != 0) or (@as(c_int, @bitCast(@as(c_uint, @as([*c]fiobj_type_enum, @ptrFromInt(o))[@as(c_uint, @intCast(@as(c_int, 0)))]))) == FIOBJ_T_NUMBER))))), @as(c_int, 1) => return @as(usize, @bitCast(@as(c_long, @intFromBool(((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) != 0) or (@as(c_int, @bitCast(@as(c_uint, @as([*c]fiobj_type_enum, @ptrFromInt(o))[@as(c_uint, @intCast(@as(c_int, 0)))]))) == FIOBJ_T_NUMBER))))),
@ -311,7 +311,7 @@ pub fn fiobj_type_is(arg_o: FIOBJ, arg_type: fiobj_type_enum) callconv(.C) usize
return @as(usize, @bitCast(@as(c_long, @intFromBool((((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6)))))) and (@as(c_int, @bitCast(@as(c_uint, @as([*c]fiobj_type_enum, @ptrCast(@alignCast(@as(?*anyopaque, @ptrFromInt(o & ~@as(usize, @bitCast(@as(c_long, @as(c_int, 7)))))))))[@as(c_uint, @intCast(@as(c_int, 0)))]))) == @as(c_int, @bitCast(@as(c_uint, @"type")))))))); return @as(usize, @bitCast(@as(c_long, @intFromBool((((o != 0) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 0)))))) and ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) != @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6)))))) and (@as(c_int, @bitCast(@as(c_uint, @as([*c]fiobj_type_enum, @ptrCast(@alignCast(@as(?*anyopaque, @ptrFromInt(o & ~@as(usize, @bitCast(@as(c_long, @as(c_int, 7)))))))))[@as(c_uint, @intCast(@as(c_int, 0)))]))) == @as(c_int, @bitCast(@as(c_uint, @"type"))))))));
} }
pub fn fiobj_type(arg_o: FIOBJ) callconv(.C) fiobj_type_enum { pub fn fiobj_type(arg_o: FIOBJ) callconv(.C) fiobj_type_enum {
var o = arg_o; const o = arg_o;
if (!(o != 0)) return @as(u8, @bitCast(@as(i8, @truncate(FIOBJ_T_NULL)))); if (!(o != 0)) return @as(u8, @bitCast(@as(i8, @truncate(FIOBJ_T_NULL))));
if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) != 0) return @as(u8, @bitCast(@as(i8, @truncate(FIOBJ_T_NUMBER)))); if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 1))))) != 0) return @as(u8, @bitCast(@as(i8, @truncate(FIOBJ_T_NUMBER))));
if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) return @as(u8, @bitCast(@as(u8, @truncate(o)))); if ((o & @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) == @as(c_ulong, @bitCast(@as(c_long, @as(c_int, 6))))) return @as(u8, @bitCast(@as(u8, @truncate(o))));
@ -326,7 +326,7 @@ pub extern const FIOBJECT_VTABLE_ARRAY: fiobj_object_vtable_s;
pub extern const FIOBJECT_VTABLE_HASH: fiobj_object_vtable_s; pub extern const FIOBJECT_VTABLE_HASH: fiobj_object_vtable_s;
pub extern const FIOBJECT_VTABLE_DATA: fiobj_object_vtable_s; pub extern const FIOBJECT_VTABLE_DATA: fiobj_object_vtable_s;
pub fn fiobj_type_vtable(arg_o: FIOBJ) callconv(.C) [*c]const fiobj_object_vtable_s { pub fn fiobj_type_vtable(arg_o: FIOBJ) callconv(.C) [*c]const fiobj_object_vtable_s {
var o = arg_o; const o = arg_o;
while (true) { while (true) {
switch (@as(c_int, @bitCast(@as(c_uint, fiobj_type(o))))) { switch (@as(c_int, @bitCast(@as(c_uint, fiobj_type(o))))) {
@as(c_int, 1) => return &FIOBJECT_VTABLE_NUMBER, @as(c_int, 1) => return &FIOBJECT_VTABLE_NUMBER,
@ -361,7 +361,7 @@ pub fn fiobj_obj2float(o: FIOBJ) callconv(.C) f64 {
pub extern fn fio_ltocstr(c_long) fio_str_info_s; pub extern fn fio_ltocstr(c_long) fio_str_info_s;
pub fn fiobj_obj2cstr(o: FIOBJ) callconv(.C) fio_str_info_s { pub fn fiobj_obj2cstr(o: FIOBJ) callconv(.C) fio_str_info_s {
if (!(o != 0)) { if (!(o != 0)) {
var ret: fio_str_info_s = fio_str_info_s{ const ret: fio_str_info_s = fio_str_info_s{
.capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))), .capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))),
.len = @as(usize, @bitCast(@as(c_long, @as(c_int, 4)))), .len = @as(usize, @bitCast(@as(c_long, @as(c_int, 4)))),
.data = @as([*c]u8, @ptrFromInt(@intFromPtr("null"))), .data = @as([*c]u8, @ptrFromInt(@intFromPtr("null"))),
@ -374,7 +374,7 @@ pub fn fiobj_obj2cstr(o: FIOBJ) callconv(.C) fio_str_info_s {
switch (@as(c_int, @bitCast(@as(c_uint, @as(u8, @bitCast(@as(u8, @truncate(o)))))))) { switch (@as(c_int, @bitCast(@as(c_uint, @as(u8, @bitCast(@as(u8, @truncate(o)))))))) {
@as(c_int, 6) => { @as(c_int, 6) => {
{ {
var ret: fio_str_info_s = fio_str_info_s{ const ret: fio_str_info_s = fio_str_info_s{
.capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))), .capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))),
.len = @as(usize, @bitCast(@as(c_long, @as(c_int, 4)))), .len = @as(usize, @bitCast(@as(c_long, @as(c_int, 4)))),
.data = @as([*c]u8, @ptrFromInt(@intFromPtr("null"))), .data = @as([*c]u8, @ptrFromInt(@intFromPtr("null"))),
@ -384,7 +384,7 @@ pub fn fiobj_obj2cstr(o: FIOBJ) callconv(.C) fio_str_info_s {
}, },
@as(c_int, 38) => { @as(c_int, 38) => {
{ {
var ret: fio_str_info_s = fio_str_info_s{ const ret: fio_str_info_s = fio_str_info_s{
.capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))), .capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))),
.len = @as(usize, @bitCast(@as(c_long, @as(c_int, 5)))), .len = @as(usize, @bitCast(@as(c_long, @as(c_int, 5)))),
.data = @as([*c]u8, @ptrFromInt(@intFromPtr("false"))), .data = @as([*c]u8, @ptrFromInt(@intFromPtr("false"))),
@ -394,7 +394,7 @@ pub fn fiobj_obj2cstr(o: FIOBJ) callconv(.C) fio_str_info_s {
}, },
@as(c_int, 22) => { @as(c_int, 22) => {
{ {
var ret: fio_str_info_s = fio_str_info_s{ const ret: fio_str_info_s = fio_str_info_s{
.capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))), .capa = @as(usize, @bitCast(@as(c_long, @as(c_int, 0)))),
.len = @as(usize, @bitCast(@as(c_long, @as(c_int, 4)))), .len = @as(usize, @bitCast(@as(c_long, @as(c_int, 4)))),
.data = @as([*c]u8, @ptrFromInt(@intFromPtr("true"))), .data = @as([*c]u8, @ptrFromInt(@intFromPtr("true"))),
@ -556,8 +556,8 @@ pub extern fn http_date2rfc7231(target: [*c]u8, tmbuf: [*c]struct_tm) usize;
pub extern fn http_date2rfc2109(target: [*c]u8, tmbuf: [*c]struct_tm) usize; pub extern fn http_date2rfc2109(target: [*c]u8, tmbuf: [*c]struct_tm) usize;
pub extern fn http_date2rfc2822(target: [*c]u8, tmbuf: [*c]struct_tm) usize; pub extern fn http_date2rfc2822(target: [*c]u8, tmbuf: [*c]struct_tm) usize;
pub fn http_date2str(arg_target: [*c]u8, arg_tmbuf: [*c]struct_tm) callconv(.C) usize { pub fn http_date2str(arg_target: [*c]u8, arg_tmbuf: [*c]struct_tm) callconv(.C) usize {
var target = arg_target; const target = arg_target;
var tmbuf = arg_tmbuf; const tmbuf = arg_tmbuf;
return http_date2rfc7231(target, tmbuf); return http_date2rfc7231(target, tmbuf);
} }
pub extern fn http_time2str(target: [*c]u8, t: time_t) usize; pub extern fn http_time2str(target: [*c]u8, t: time_t) usize;

View file

@ -122,7 +122,7 @@ pub fn Basic(comptime Lookup: type, comptime kind: BasicAuthStrategy) type {
); );
return .AuthFailed; return .AuthFailed;
} }
var decoded = buffer[0..decoded_size]; const decoded = buffer[0..decoded_size];
decoder.decode(decoded, encoded) catch |err| { decoder.decode(decoded, encoded) catch |err| {
zap.debug( zap.debug(
"ERROR: UserPassAuth: unable to decode `{s}`: {any}\n", "ERROR: UserPassAuth: unable to decode `{s}`: {any}\n",
@ -400,7 +400,7 @@ pub fn UserPassSession(comptime Lookup: type, comptime lockedPwLookups: bool) ty
lookup: *Lookup, lookup: *Lookup,
args: UserPassSessionArgs, args: UserPassSessionArgs,
) !Self { ) !Self {
var ret: Self = .{ const ret: Self = .{
.allocator = allocator, .allocator = allocator,
.settings = .{ .settings = .{
.usernameParam = try allocator.dupe(u8, args.usernameParam), .usernameParam = try allocator.dupe(u8, args.usernameParam),

View file

@ -82,7 +82,7 @@ pub fn EndpointHandler(comptime HandlerType: anytype, comptime ContextType: anyt
/// If `breakOnFinish` is `true`, the handler will stop handing requests down the chain if /// If `breakOnFinish` is `true`, the handler will stop handing requests down the chain if
/// the endpoint processed the request. /// the endpoint processed the request.
pub fn onRequest(handler: *HandlerType, r: zap.Request, context: *ContextType) bool { pub fn onRequest(handler: *HandlerType, r: zap.Request, context: *ContextType) bool {
var self = @fieldParentPtr(Self, "handler", handler); const self: *Self = @fieldParentPtr("handler", handler);
r.setUserContext(context); r.setUserContext(context);
self.endpoint.onRequest(r); self.endpoint.onRequest(r);

View file

@ -146,10 +146,10 @@ fn makeRequest(a: std.mem.Allocator, url: []const u8, auth: ?ClientAuthReqHeader
var http_client: std.http.Client = .{ .allocator = a }; var http_client: std.http.Client = .{ .allocator = a };
defer http_client.deinit(); defer http_client.deinit();
var req = try http_client.request(.GET, uri, h, .{}); var req = try http_client.open(.GET, uri, h, .{});
defer req.deinit(); defer req.deinit();
try req.start(); try req.send(.{});
try req.wait(); try req.wait();
// req.deinit() panics! // req.deinit() panics!
// defer req.deinit(); // defer req.deinit();

View file

@ -10,10 +10,10 @@ fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a }; var http_client: std.http.Client = .{ .allocator = a };
defer http_client.deinit(); defer http_client.deinit();
var req = try http_client.request(.GET, uri, h, .{}); var req = try http_client.open(.GET, uri, h, .{});
defer req.deinit(); defer req.deinit();
try req.start(); try req.send(.{});
try req.wait(); try req.wait();
zap.stop(); zap.stop();
} }
@ -23,7 +23,7 @@ fn makeRequestThread(a: std.mem.Allocator, url: []const u8) !std.Thread {
} }
test "http parameters" { test "http parameters" {
var allocator = std.testing.allocator; const allocator = std.testing.allocator;
const Handler = struct { const Handler = struct {
var alloc: std.mem.Allocator = undefined; var alloc: std.mem.Allocator = undefined;

View file

@ -15,10 +15,10 @@ fn makeRequest(a: std.mem.Allocator, url: []const u8) !void {
var http_client: std.http.Client = .{ .allocator = a }; var http_client: std.http.Client = .{ .allocator = a };
defer http_client.deinit(); defer http_client.deinit();
var req = try http_client.request(.GET, uri, h, .{}); var req = try http_client.open(.GET, uri, h, .{});
defer req.deinit(); defer req.deinit();
try req.start(); try req.send(.{});
try req.wait(); try req.wait();
read_len = try req.readAll(&buffer); read_len = try req.readAll(&buffer);
@ -33,7 +33,7 @@ pub fn on_request(r: zap.Request) void {
} }
test "send file" { test "send file" {
var allocator = std.testing.allocator; const allocator = std.testing.allocator;
// setup listener // setup listener
var listener = zap.HttpListener.init( var listener = zap.HttpListener.init(

View file

@ -50,7 +50,7 @@ pub fn Handler(comptime ContextType: type) type {
/// This function will end the HTTP stage of the connection and attempt to "upgrade" to a WebSockets connection. /// This function will end the HTTP stage of the connection and attempt to "upgrade" to a WebSockets connection.
pub fn upgrade(h: [*c]fio.http_s, settings: *WebSocketSettings) WebSocketError!void { pub fn upgrade(h: [*c]fio.http_s, settings: *WebSocketSettings) WebSocketError!void {
var fio_settings: fio.websocket_settings_s = .{ const fio_settings: fio.websocket_settings_s = .{
.on_message = internal_on_message, .on_message = internal_on_message,
.on_open = internal_on_open, .on_open = internal_on_open,
.on_ready = internal_on_ready, .on_ready = internal_on_ready,
@ -64,8 +64,8 @@ pub fn Handler(comptime ContextType: type) type {
} }
fn internal_on_message(handle: WsHandle, msg: fio.fio_str_info_s, is_text: u8) callconv(.C) void { fn internal_on_message(handle: WsHandle, msg: fio.fio_str_info_s, is_text: u8) callconv(.C) void {
var user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle)))); const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle))));
var message = msg.data[0..msg.len]; const message = msg.data[0..msg.len];
if (user_provided_settings) |settings| { if (user_provided_settings) |settings| {
if (settings.on_message) |on_message| { if (settings.on_message) |on_message| {
on_message(settings.context, handle, message, is_text == 1); on_message(settings.context, handle, message, is_text == 1);
@ -74,7 +74,7 @@ pub fn Handler(comptime ContextType: type) type {
} }
fn internal_on_open(handle: WsHandle) callconv(.C) void { fn internal_on_open(handle: WsHandle) callconv(.C) void {
var user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle)))); const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle))));
if (user_provided_settings) |settings| { if (user_provided_settings) |settings| {
if (settings.on_open) |on_open| { if (settings.on_open) |on_open| {
on_open(settings.context, handle); on_open(settings.context, handle);
@ -83,7 +83,7 @@ pub fn Handler(comptime ContextType: type) type {
} }
fn internal_on_ready(handle: WsHandle) callconv(.C) void { fn internal_on_ready(handle: WsHandle) callconv(.C) void {
var user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle)))); const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle))));
if (user_provided_settings) |settings| { if (user_provided_settings) |settings| {
if (settings.on_ready) |on_ready| { if (settings.on_ready) |on_ready| {
on_ready(settings.context, handle); on_ready(settings.context, handle);
@ -92,7 +92,7 @@ pub fn Handler(comptime ContextType: type) type {
} }
fn internal_on_shutdown(handle: WsHandle) callconv(.C) void { fn internal_on_shutdown(handle: WsHandle) callconv(.C) void {
var user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle)))); const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(fio.websocket_udata_get(handle))));
if (user_provided_settings) |settings| { if (user_provided_settings) |settings| {
if (settings.on_shutdown) |on_shutdown| { if (settings.on_shutdown) |on_shutdown| {
on_shutdown(settings.context, handle); on_shutdown(settings.context, handle);
@ -101,7 +101,7 @@ pub fn Handler(comptime ContextType: type) type {
} }
fn internal_on_close(uuid: isize, udata: ?*anyopaque) callconv(.C) void { fn internal_on_close(uuid: isize, udata: ?*anyopaque) callconv(.C) void {
var user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(udata))); const user_provided_settings: ?*WebSocketSettings = @as(?*WebSocketSettings, @ptrCast(@alignCast(udata)));
if (user_provided_settings) |settings| { if (user_provided_settings) |settings| {
if (settings.on_close) |on_close| { if (settings.on_close) |on_close| {
on_close(settings.context, uuid); on_close(settings.context, uuid);
@ -119,7 +119,7 @@ pub fn Handler(comptime ContextType: type) type {
pub inline fn write(handle: WsHandle, message: []const u8, is_text: bool) WebSocketError!void { pub inline fn write(handle: WsHandle, message: []const u8, is_text: bool) WebSocketError!void {
if (fio.websocket_write( if (fio.websocket_write(
handle, handle,
fio.str2fio(message), util.str2fio(message),
if (is_text) 1 else 0, if (is_text) 1 else 0,
) != 0) { ) != 0) {
return error.WriteError; return error.WriteError;
@ -192,7 +192,7 @@ pub fn Handler(comptime ContextType: type) type {
/// we need it to look up the ziggified callbacks. /// we need it to look up the ziggified callbacks.
pub inline fn subscribe(handle: WsHandle, args: *SubscribeArgs) WebSocketError!usize { pub inline fn subscribe(handle: WsHandle, args: *SubscribeArgs) WebSocketError!usize {
if (handle == null) return error.SubscribeError; if (handle == null) return error.SubscribeError;
var fio_args: fio.websocket_subscribe_s_zigcompat = .{ const fio_args: fio.websocket_subscribe_s_zigcompat = .{
.ws = handle.?, .ws = handle.?,
.channel = util.str2fio(args.channel), .channel = util.str2fio(args.channel),
.on_message = if (args.on_message) |_| internal_subscription_on_message else null, .on_message = if (args.on_message) |_| internal_subscription_on_message else null,

View file

@ -43,7 +43,7 @@ pub const Tls = @import("tls.zig");
/// } /// }
/// ///
/// fn get(e: *zap.Endpoint, r: zap.Request) void { /// fn get(e: *zap.Endpoint, r: zap.Request) void {
/// const self: *StopEndpoint = @fieldParentPtr(StopEndpoint, "ep", e); /// const self: *StopEndpoint = @fieldParentPtr("ep", e);
/// _ = self; /// _ = self;
/// _ = r; /// _ = r;
/// zap.stop(); /// zap.stop();

View file

@ -28,7 +28,8 @@ fn usage() void {
\\ instructions \\ instructions
; ;
std.debug.print("{s}", .{message}); std.debug.print("{s}", .{message});
std.os.exit(1);
std.process.exit(1);
} }
var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){};
@ -88,7 +89,7 @@ fn get_tag_annotation(allocator: std.mem.Allocator, tagname: []const u8) ![]cons
tagname, tagname,
}; };
const result = try std.ChildProcess.exec(.{ const result = try std.ChildProcess.run(.{
.allocator = allocator, .allocator = allocator,
.argv = &args, .argv = &args,
}); });
@ -150,24 +151,26 @@ fn sendToDiscordPart(allocator: std.mem.Allocator, url: []const u8, message_json
// url // url
const uri = try std.Uri.parse(url); const uri = try std.Uri.parse(url);
// http headers
var h = std.http.Headers{ .allocator = allocator };
defer h.deinit();
try h.append("accept", "*/*");
try h.append("Content-Type", "application/json");
// client // client
var http_client: std.http.Client = .{ .allocator = allocator }; var http_client: std.http.Client = .{ .allocator = allocator };
defer http_client.deinit(); defer http_client.deinit();
var server_header_buffer: [2048]u8 = undefined;
// request // request
var req = try http_client.request(.POST, uri, h, .{}); var req = try http_client.open(.POST, uri, .{
.server_header_buffer = &server_header_buffer,
.extra_headers = &.{
.{ .name = "accept", .value = "*/*" },
.{ .name = "Content-Type", .value = "application/json" },
},
});
defer req.deinit(); defer req.deinit();
req.transfer_encoding = .chunked; req.transfer_encoding = .chunked;
// connect, send request // connect, send request
try req.start(); try req.send();
// send POST payload // send POST payload
try req.writer().writeAll(message_json); try req.writer().writeAll(message_json);
@ -182,7 +185,7 @@ fn sendToDiscordPart(allocator: std.mem.Allocator, url: []const u8, message_json
fn sendToDiscord(allocator: std.mem.Allocator, url: []const u8, message: []const u8) !void { fn sendToDiscord(allocator: std.mem.Allocator, url: []const u8, message: []const u8) !void {
// json payload // json payload
// max size: 100kB // max size: 100kB
var buf: []u8 = try allocator.alloc(u8, 100 * 1024); const buf: []u8 = try allocator.alloc(u8, 100 * 1024);
defer allocator.free(buf); defer allocator.free(buf);
var fba = std.heap.FixedBufferAllocator.init(buf); var fba = std.heap.FixedBufferAllocator.init(buf);
var string = std.ArrayList(u8).init(fba.allocator()); var string = std.ArrayList(u8).init(fba.allocator());
@ -336,7 +339,7 @@ fn command_announce(allocator: std.mem.Allocator, tag: []const u8) !void {
defer allocator.free(url); defer allocator.free(url);
sendToDiscord(allocator, url, announcement) catch |err| { sendToDiscord(allocator, url, announcement) catch |err| {
std.debug.print("HTTP ERROR: {any}\n", .{err}); std.debug.print("HTTP ERROR: {any}\n", .{err});
std.os.exit(1); std.process.exit(1);
}; };
} }
@ -399,7 +402,7 @@ fn command_update_readme(allocator: std.mem.Allocator, tag: []const u8) !void {
// we need to put the \n back in. // we need to put the \n back in.
// TODO: change this by using some "search" iterator that just // TODO: change this by using some "search" iterator that just
// returns indices etc // returns indices etc
var output_line = try std.fmt.allocPrint(allocator, "{s}\n", .{line}); const output_line = try std.fmt.allocPrint(allocator, "{s}\n", .{line});
defer allocator.free(output_line); defer allocator.free(output_line);
_ = try writer.write(output_line); _ = try writer.write(output_line);
} }

View file

@ -18,7 +18,10 @@ Modify your `build.zig.zon` like this:
.zap = .{ .zap = .{
.url = "https://github.com/zigzap/zap/archive/refs/tags/{tag}.tar.gz", .url = "https://github.com/zigzap/zap/archive/refs/tags/{tag}.tar.gz",
.hash = "{hash}", .hash = "{hash}",
} },
.paths = .{
"",
},
} }
} }

View file

@ -6,9 +6,14 @@
.dependencies = .{ .dependencies = .{
// zap {tag} // zap {tag}
.zap = .{ .zap = .{
.url = "https://github.com/zigzap/zap/archive/refs/tags/{tag}.tar.gz", // when tagged:
// .url = "https://github.com/zigzap/zap/archive/refs/tags/{tag}.tar.gz",
.url = "https://github.com/zigzap/zap/archive/{tag}.tar.gz",
.hash = "{hash}", .hash = "{hash}",
} },
.paths = .{
"",
},
} }
} }
``` ```

View file

@ -28,7 +28,10 @@ Here is a complete `build.zig.zon` example:
.zap = .{ .zap = .{
.url = "https://github.com/zigzap/zap/archive/refs/tags/{tag}.tar.gz", .url = "https://github.com/zigzap/zap/archive/refs/tags/{tag}.tar.gz",
.hash = "{hash}", .hash = "{hash}",
} },
.paths = .{
"",
},
} }
} }
@ -41,7 +44,8 @@ Then, in your `build.zig`'s `build` function, add the following before
const zap = b.dependency("zap", .{ const zap = b.dependency("zap", .{
.target = target, .target = target,
.optimize = optimize, .optimize = optimize,
.openssl = false, // set to true to enable TLS support
}); });
exe.addModule("zap", zap.module("zap")); exe.root_module.addImport("zap", zap.module("zap"));
exe.linkLibrary(zap.artifact("facil.io")); exe.linkLibrary(zap.artifact("facil.io"));
``` ```

44
tools/docserver.zig Normal file
View file

@ -0,0 +1,44 @@
const std = @import("std");
const zap = @import("zap");
fn on_request(r: zap.Request) void {
r.setStatus(.not_found);
r.sendBody("<html><body><h1>404 - File not found</h1></body></html>") catch return;
}
pub fn main() !void {
var args_it = std.process.args();
var port: usize = 8080;
var docs_dir: []const u8 = "zig-out/docs";
while (args_it.next()) |arg| {
if (std.mem.startsWith(u8, arg, "--port=")) {
// try to parse port
if (std.fmt.parseUnsigned(usize, arg[7..], 0)) |the_port| {
port = the_port;
} else |_| {
std.debug.print("Invalid port number. Using default port {}\n", .{port});
}
}
if (std.mem.startsWith(u8, arg, "--docs=")) {
docs_dir = arg[7..];
}
}
var listener = zap.HttpListener.init(.{
.port = port,
.on_request = on_request,
.public_folder = docs_dir,
.log = true,
});
try listener.listen();
std.debug.print("\nServing docs from {s} at 0.0.0.0:{}\n", .{ docs_dir, port });
// start worker threads
zap.start(.{
.threads = 2,
.workers = 1,
});
}

View file

@ -71,7 +71,7 @@ pub const usage_pkg =
; ;
pub fn gitLatestTag(gpa: Allocator, pkg_dir: []const u8) ![]const u8 { pub fn gitLatestTag(gpa: Allocator, pkg_dir: []const u8) ![]const u8 {
const result = try std.ChildProcess.exec(.{ const result = try std.ChildProcess.run(.{
.allocator = gpa, .allocator = gpa,
.argv = &.{ .argv = &.{
"git", "git",
@ -97,7 +97,7 @@ pub fn gitLatestTag(gpa: Allocator, pkg_dir: []const u8) ![]const u8 {
} }
pub fn gitFileList(gpa: Allocator, pkg_dir: []const u8) ![]const u8 { pub fn gitFileList(gpa: Allocator, pkg_dir: []const u8) ![]const u8 {
const result = try std.ChildProcess.exec(.{ const result = try std.ChildProcess.run(.{
.allocator = gpa, .allocator = gpa,
.argv = &.{ .argv = &.{
"git", "git",
@ -266,8 +266,8 @@ pub fn cmdPkg(gpa: Allocator, arena: Allocator, args: []const []const u8) !void
// computePackageHash will close the directory after completion // computePackageHash will close the directory after completion
// std.debug.print("abspath: {s}\n", .{cwd_absolute_path}); // std.debug.print("abspath: {s}\n", .{cwd_absolute_path});
var cwd_copy = try fs.openIterableDirAbsolute(cwd_absolute_path, .{}); var cwd_copy = try fs.openDirAbsolute(cwd_absolute_path, .{});
errdefer cwd_copy.dir.close(); errdefer cwd_copy.close();
var thread_pool: ThreadPool = undefined; var thread_pool: ThreadPool = undefined;
try thread_pool.init(.{ .allocator = gpa }); try thread_pool.init(.{ .allocator = gpa });
@ -281,7 +281,7 @@ pub fn cmdPkg(gpa: Allocator, arena: Allocator, args: []const []const u8) !void
}; };
break :blk try computePackageHashExcludingDirectories( break :blk try computePackageHashExcludingDirectories(
&thread_pool, &thread_pool,
.{ .dir = cwd_copy.dir }, cwd_copy,
excluded_directories, excluded_directories,
); );
}; };
@ -355,7 +355,7 @@ fn isExecutable(file: fs.File) !bool {
pub fn computePackageHashExcludingDirectories( pub fn computePackageHashExcludingDirectories(
thread_pool: *ThreadPool, thread_pool: *ThreadPool,
pkg_dir: fs.IterableDir, pkg_dir: fs.Dir,
excluded_directories: []const []const u8, excluded_directories: []const []const u8,
) ![Manifest.Hash.digest_length]u8 { ) ![Manifest.Hash.digest_length]u8 {
const gpa = thread_pool.allocator; const gpa = thread_pool.allocator;
@ -405,7 +405,7 @@ pub fn computePackageHashExcludingDirectories(
.failure = undefined, // to be populated by the worker .failure = undefined, // to be populated by the worker
}; };
wait_group.start(); wait_group.start();
try thread_pool.spawn(workerHashFile, .{ pkg_dir.dir, hashed_file, &wait_group }); try thread_pool.spawn(workerHashFile, .{ pkg_dir, hashed_file, &wait_group });
try all_files.append(hashed_file); try all_files.append(hashed_file);
} }

View file

@ -1,43 +1,33 @@
const std = @import("std"); const std = @import("std");
pub fn main() !void { pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{ // var gpa = std.heap.GeneralPurposeAllocator(.{
.thread_safe = true, // .thread_safe = true,
}){}; // }){};
var allocator = gpa.allocator(); // const allocator = gpa.allocator();
var server = std.http.Server.init(allocator, .{
.reuse_address = true,
});
defer server.deinit();
const address = try std.net.Address.parseIp("127.0.0.1", 3000); const address = try std.net.Address.parseIp("127.0.0.1", 3000);
try server.listen(address); var http_server = try address.listen(.{
.reuse_address = true,
});
const max_header_size = 8192; var read_buffer: [2048]u8 = undefined;
// const max_header_size = 8192;
while (true) { while (true) {
var res = try server.accept(.{ const connection = try http_server.accept();
.allocator = allocator, defer connection.stream.close();
.header_strategy = .{ .dynamic = max_header_size }, var server = std.http.Server.init(connection, &read_buffer);
});
// const start_time = std.time.nanoTimestamp();
defer res.deinit();
defer _ = res.reset();
try res.wait();
var request = try server.receiveHead();
const server_body: []const u8 = "HI FROM ZIG STD!\n"; const server_body: []const u8 = "HI FROM ZIG STD!\n";
res.transfer_encoding = .{ .content_length = server_body.len };
try res.headers.append("content-type", "text/plain");
try res.headers.append("connection", "close");
try res.do();
var buf: [128]u8 = undefined; try request.respond(server_body, .{
_ = try res.readAll(&buf); .extra_headers = &.{
_ = try res.writer().writeAll(server_body); .{ .name = "content_type", .value = "text/plain" },
try res.finish(); .{ .name = "connection", .value = "close" },
// const end_time = std.time.nanoTimestamp(); },
// const diff = end_time - start_time; });
// std.debug.print("{d}\n", .{diff});
} }
} }