diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..41167a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +event-processor +zig-cache/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..4c98c0f --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "routez"] + path = routez + url = https://github.com/elerch/routez.git diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0feb744 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Emil Lerch + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..48dfffa --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +event-processor: zig-cache/bin/event-processor + @cp zig-cache/bin/event-processor event-processor + @strip event-processor + +zig-cache/bin/event-processor: src/main.zig + @zig build -Drelease-safe=true + +clean: + @rm -r zig-cache + @rm event-processor diff --git a/README.md b/README.md new file mode 100644 index 0000000..ff90fd6 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Event processor + +This project creates a web server, listening on port 9090, that will capture +all requests and send the path, method, headers and body in JSON format +asynchronously to a program called "event-processor", which can then do +whatever it wants with it. + +# Building + +Install zig 0.7.1 from https://ziglang.org/download/. Once downloaded, you +can unpackage the download and get the main executable in your path (zig +figures out the other files it needs based on where the main executable lies). + +You can either run "make" using the Makefile provided, or run `zig build`. +Doing the latter will land the binary in ./zig-cache/bin. The makefile uses +-Drelease-safe=true to provide a small, statically-linked reproducible binary, +which is then stripped and copied to "event-processor-backend" in the +current directory. diff --git a/build.zig b/build.zig new file mode 100644 index 0000000..5d026aa --- /dev/null +++ b/build.zig @@ -0,0 +1,33 @@ +const std = @import("std"); +const Builder = std.build.Builder; + +pub fn build(b: *Builder) void { + // Standard target options allows the person running `zig build` to choose + // what target to build for. Here we do not override the defaults, which + // means any target is allowed, and the default is native. Other options + // for restricting supported target set are available. + const target = b.standardTargetOptions(.{}); + + // Standard release options allow the person running `zig build` to select + // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. + const mode = b.standardReleaseOptions(); + + const exe = b.addExecutable("event-processor", "src/main.zig"); + exe.addPackage(.{ + .name = "routez", + .path = "routez/src/routez.zig", + .dependencies = &[_]std.build.Pkg{.{ + .name = "zuri", + .path = "routez/zuri/src/zuri.zig", + }}, + }); + exe.setTarget(target); + exe.setBuildMode(mode); + exe.install(); + + const run_cmd = exe.run(); + run_cmd.step.dependOn(b.getInstallStep()); + + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); +} diff --git a/routez b/routez new file mode 160000 index 0000000..1c68837 --- /dev/null +++ b/routez @@ -0,0 +1 @@ +Subproject commit 1c688374385d570784647f1bb80bee61e55fffb1 diff --git a/src/main.zig b/src/main.zig new file mode 100644 index 0000000..7812639 --- /dev/null +++ b/src/main.zig @@ -0,0 +1,70 @@ +const std = @import("std"); +const fmt = std.fmt; +const json = std.json; +const Address = std.net.Address; +usingnamespace @import("routez"); +const allocator = std.heap.page_allocator; + +// zig compiler error spawning processes with >0.6.0 evented IO +//pub const io_mode = .evented; + +pub const RequestResponse = struct { + method: []const u8, + headers: Headers, + path: []const u8, + query: []const u8, + body: []const u8, +}; + +pub fn main() !void { + var server = Server.init( + allocator, + .{}, + .{ + all("*", allHandler), + }, + ); + var addr = try Address.parseIp("0.0.0.0", 9090); + try server.listen(addr); +} + +fn allHandler(req: Request, res: Response) !void { + const Header = struct { + name: []const u8, + value: []const u8, + }; + const Res_response = struct { + method: []const u8, + headers: []Header, + path: []const u8, + query: []const u8, + body: []const u8, + //version: Version, + }; + var res_headers = try allocator.alloc(Header, req.headers.list.items.len); + defer allocator.free(res_headers); + for (req.headers.list.items) |h, i| { + res_headers[i] = Header{ .name = h.name, .value = h.value }; + } + + var arr = std.ArrayList(u8).init(allocator); + defer arr.deinit(); + try json.stringify(Res_response{ + .method = req.method, + .headers = res_headers, + .path = req.path, + .query = req.query, + .body = req.body, + }, json.StringifyOptions{}, arr.writer()); + + _ = async launchProcess(arr.items); + + res.status_code = StatusCode.Accepted; + try res.body.writeAll("Accepted\n"); +} + +fn launchProcess(items: []const u8) !void { + const process = try std.ChildProcess.init(&[_][]const u8{ "event-processor-backend", items }, allocator); + defer process.deinit(); + _ = try process.spawnAndWait(); +}