aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Ashby <martin@ashbysoft.com>2023-08-22 10:09:50 +0100
committerMartin Ashby <martin@ashbysoft.com>2023-08-22 10:10:02 +0100
commit8f7f272d68b4197f17d1e76c97546017b8ebea90 (patch)
tree2554b41d34faa0d9ff32eefb9cdb4b9b8c08770a
parente122e8247a3122c7996de689213066ce66d0e8b9 (diff)
downloadmfashby.net-8f7f272d68b4197f17d1e76c97546017b8ebea90.tar.gz
mfashby.net-8f7f272d68b4197f17d1e76c97546017b8ebea90.tar.bz2
mfashby.net-8f7f272d68b4197f17d1e76c97546017b8ebea90.tar.xz
mfashby.net-8f7f272d68b4197f17d1e76c97546017b8ebea90.zip
Switch to CGI comments
-rw-r--r--Caddyfile7
-rwxr-xr-xdeploy.sh36
-rw-r--r--zig-comments/comments.service12
m---------zig-comments/lib/zigwebserver0
-rw-r--r--zig-comments/src/main.zig123
-rw-r--r--zig-comments/src/templates/notfound.html2
6 files changed, 128 insertions, 52 deletions
diff --git a/Caddyfile b/Caddyfile
index 7287822..95fddd6 100644
--- a/Caddyfile
+++ b/Caddyfile
@@ -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
diff --git a/deploy.sh b/deploy.sh
index ec0a5e8..4b6511d 100755
--- a/deploy.sh
+++ b/deploy.sh
@@ -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>