diff options
-rw-r--r-- | Caddyfile | 7 | ||||
-rwxr-xr-x | deploy.sh | 36 | ||||
-rw-r--r-- | zig-comments/comments.service | 12 | ||||
m--------- | zig-comments/lib/zigwebserver | 0 | ||||
-rw-r--r-- | zig-comments/src/main.zig | 123 | ||||
-rw-r--r-- | zig-comments/src/templates/notfound.html | 2 |
6 files changed, 128 insertions, 52 deletions
@@ -1,8 +1,13 @@ +{ + order cgi before respond +} + http://localhost:8080 { root * public # API server - reverse_proxy /api/* localhost:5678 + #reverse_proxy /api/* localhost:5678 + cgi /api/* zig-comments/zig-out/bin/comments # Redirects for old assets redir /10-11-21-longboard-slides.mp4 /assets/10-11-21-longboard-slides.mp4 permanent @@ -6,21 +6,21 @@ set -e hugo # Build comments app -pushd comments +# pushd comments +# if [ $(uname -m) != "aarch64" ] +# then +# RUSTFLAGS="-C linker=aarch64-linux-gnu-gcc" +# fi +# cargo build --target=aarch64-unknown-linux-gnu --release +# popd +pushd zig-comments if [ $(uname -m) != "aarch64" ] then - RUSTFLAGS="-C linker=aarch64-linux-gnu-gcc" + echo "must build on aarch64 for now" + exit fi -cargo build --target=aarch64-unknown-linux-gnu --release +zig build # -Doptimize=ReleaseSafe popd -#pushd zig-comments -#if [ $(uname -m) != "aarch64" ] -#then -# echo "must build on aarch64 for now" -# exit -#fi -#zig build # -Doptimize=ReleaseSafe -#popd # TODO update caddy with offline message while site being updated @@ -28,12 +28,12 @@ popd rsync -rz public/* root@rpi3:/var/www/mfashby.net # Copy comments app and reboot -ssh root@rpi3 -C systemctl stop comments -rsync comments/target/aarch64-unknown-linux-gnu/release/comments root@rpi3:/usr/local/bin/comments -rsync comments/comments.service root@rpi3:/etc/systemd/system/comments.service -#rsync zig-comments/zig-out/bin/comments root@rpi3:/usr/local/bin/comments -#rsync zig-comments/comments.service root@rpi3:/etc/systemd/system/comments.service -ssh root@rpi3 -C systemctl daemon-reload -ssh root@rpi3 -C systemctl restart comments +#ssh root@rpi3 -C systemctl stop comments +#rsync comments/target/aarch64-unknown-linux-gnu/release/comments root@rpi3:/usr/local/bin/comments +#rsync comments/comments.service root@rpi3:/etc/systemd/system/comments.service +#ssh root@rpi3 -C systemctl daemon-reload +#ssh root@rpi3 -C systemctl restart comments + +rsync zig-comments/zig-out/bin/comments root@rpi3:/usr/local/bin/comments # TODO set caddy back to online diff --git a/zig-comments/comments.service b/zig-comments/comments.service deleted file mode 100644 index 7d8f0e5..0000000 --- a/zig-comments/comments.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Comments service -After=postgres.service - -[Service] -User=comments -ExecStart=/usr/local/bin/comments -Restart=on-failure -EnvironmentFile=/etc/sysconfig/comments - -[Install] -WantedBy=multi-user.target diff --git a/zig-comments/lib/zigwebserver b/zig-comments/lib/zigwebserver -Subproject 17d8cc65fe6396d505dda6bf162942cab9e0040 +Subproject 0736c8a26dbd970670117290baf4a68e430aeca diff --git a/zig-comments/src/main.zig b/zig-comments/src/main.zig index b8b820c..898b689 100644 --- a/zig-comments/src/main.zig +++ b/zig-comments/src/main.zig @@ -5,7 +5,35 @@ const mustache = @import("mustache"); const Params = zws.Params; -const Err = error{ Overflow, InvalidCharacter, StreamTooLong, ColumnNotFound } || pq.PqError || std.http.Server.Response.WaitError || std.http.Server.Response.DoError || std.http.Server.Response.ReadError || std.http.Server.Response.FinishError || zws.Path.ParseError; +const Err = error{ + Unexpected, + AccessDenied, + OutOfMemory, + InputOutput, + SystemResources, + IsDir, + OperationAborted, + BrokenPipe, + ConnectionResetByPeer, + ConnectionTimedOut, + NotOpenForReading, + NetNameDeleted, + WouldBlock, + StreamTooLong, + Malformatted, + InvalidLength, + InvalidCharacter, + NoSpaceLeft, + PqError, + ColumnNotFound, + DiskQuota, + FileTooBig, + DeviceBusy, + InvalidArgument, + NotOpenForWriting, + LockViolation, + InvalidRequestMethod, +}; const Ctx = struct { db: pq.Db, pub fn clone(self: @This()) Ctx { @@ -19,8 +47,56 @@ const Ctx = struct { }; var gpa = std.heap.GeneralPurposeAllocator(.{}){}; -const Rtr = zws.Router(Ctx, Err); +const Request = struct { + method: std.http.Method, + target: []const u8, +}; +const ResponseTransfer = union(enum) { + content_length: u64, + chunked: void, + none: void, +}; +const Headers = struct { + const Entry = struct { key: []const u8, val: []const u8 }; + _internal: std.ArrayList(Entry), + + fn init(allocator: std.mem.Allocator) Headers { + return .{ ._internal = std.ArrayList(Entry).init(allocator) }; + } + fn append(self: *@This(), key: []const u8, val: []const u8) !void { + try self._internal.append(.{ .key = key, .val = val }); + } +}; +const Response = struct { + allocator: std.mem.Allocator, + request: Request, + // TODO other fields and writer function to write headers and body to stdout + status: std.http.Status, + transfer_encoding: ResponseTransfer, + headers: Headers, + fn reader(_: @This()) std.fs.File.Reader { + return std.io.getStdIn().reader(); + } + fn do(self: @This()) !void { + for (self.headers._internal.items) |tup| { + try std.io.getStdOut().writeAll(tup.key); + try std.io.getStdOut().writeAll(": "); + try std.io.getStdOut().writeAll(tup.val); + try std.io.getStdOut().writeAll("\r\n"); + } + try std.io.getStdOut().writeAll("\r\n"); + } + fn writer(_: @This()) std.fs.File.Writer { + return std.io.getStdOut().writer(); + } + fn finish(_: @This()) !void { + // TODO Write empty lines? or just do nothing + } +}; + +const Rtr = zws.Router(*Response, Ctx, Err); const router = Rtr{ + .allocator = gpa.allocator(), .handlers = &[_]Rtr.Handler{ .{ .method = .GET, @@ -41,43 +117,51 @@ const router = Rtr{ .notfound = notfound, }; +/// Run as a CGI program! pub fn main() !void { + const allocator = gpa.allocator(); const db_url = std.os.getenv("DATABASE_URL") orelse "postgresql://comments@localhost/comments"; var db = try pq.Db.init(db_url); - try db.exec(@embedFile("migrations/0_init.sql")); - try db.exec(@embedFile("migrations/1_capcha.sql")); + // try db.exec(@embedFile("migrations/0_init.sql")); + // try db.exec(@embedFile("migrations/1_capcha.sql")); defer db.deinit(); - const server = zws.Server(Ctx, Rtr){ - .allocator = gpa.allocator(), - .address = std.net.Address{ .in = std.net.Ip4Address.init(.{ 127, 0, 0, 1 }, 5678) }, - .context = Ctx{ .db = db }, - .handler = router, + const req = Request{ + .method = std.meta.stringToEnum(std.http.Method, std.os.getenv("REQUEST_METHOD") orelse "GET") orelse { + return error.InvalidRequestMethod; + }, + .target = std.os.getenv("REQUEST_URI") orelse "/", }; - - try server.serve(); + var res = Response{ + .allocator = allocator, + .request = req, + .status = .bad_request, + .transfer_encoding = .none, + .headers = Headers.init(allocator), + }; + const ctx = Ctx{ .db = db }; + try router.handle(&res, ctx); } -fn notfound(res: *std.http.Server.Response, _: Ctx) Err!void { +fn notfound(res: *Response, _: Ctx) Err!void { const rr = @embedFile("templates/notfound.html"); try constresponse(res, rr, .not_found); } -fn badrequest(res: *std.http.Server.Response, _: Ctx) Err!void { +fn badrequest(res: *Response, _: Ctx) Err!void { const rr = @embedFile("templates/badrequest.html"); try constresponse(res, rr, .bad_request); } -fn constresponse(res: *std.http.Server.Response, rr: []const u8, status: std.http.Status) Err!void { +fn constresponse(res: *Response, rr: []const u8, status: std.http.Status) Err!void { res.status = status; res.transfer_encoding = .{ .content_length = rr.len }; try res.headers.append("content-type", "text/html"); try res.do(); - try res.writeAll(rr); + try res.writer().writeAll(rr); try res.finish(); } -fn get_comment(res: *std.http.Server.Response, ctx: Ctx, params: Params) Err!void { - _ = params; +fn get_comment(res: *Response, ctx: Ctx, _: Params) Err!void { var p = try zws.Path.parse(res.allocator, res.request.target); defer p.deinit(); const url: []const u8 = try p.get_query_param("url") orelse { @@ -100,7 +184,6 @@ fn get_comment(res: *std.http.Server.Response, ctx: Ctx, params: Params) Err!voi const cmt = try stmt.read_struct(Comment); try comments.append(cmt); } - std.log.debug("found {} comments for url {s}", .{ comments.items.len, url }); const rr = @embedFile("templates/comments.html"); const tt = comptime mustache.parseComptime(rr, .{}, .{}); @@ -117,7 +200,7 @@ fn get_comment(res: *std.http.Server.Response, ctx: Ctx, params: Params) Err!voi try res.finish(); } -fn post_comment(res: *std.http.Server.Response, ctx: Ctx, _: Params) Err!void { +fn post_comment(res: *Response, ctx: Ctx, _: Params) Err!void { var body_aa = std.ArrayList(u8).init(res.allocator); try res.reader().readAllArrayList(&body_aa, 1_000_000); var body = try body_aa.toOwnedSlice(); @@ -169,7 +252,7 @@ fn post_comment(res: *std.http.Server.Response, ctx: Ctx, _: Params) Err!void { try res.finish(); } -fn get_form(res: *std.http.Server.Response, ctx: Ctx, _: Params) Err!void { +fn get_form(res: *Response, ctx: Ctx, _: Params) Err!void { var p = try zws.Path.parse(res.allocator, res.request.target); defer p.deinit(); const url: []const u8 = try p.get_query_param("url") orelse { diff --git a/zig-comments/src/templates/notfound.html b/zig-comments/src/templates/notfound.html index 417e20d..795d262 100644 --- a/zig-comments/src/templates/notfound.html +++ b/zig-comments/src/templates/notfound.html @@ -1,4 +1,4 @@ -<doctype HTML> +<!doctype HTML> <html> <body> <p>Not found!</p> |