From 0284553f75fd927091dc35c502e37df856af05b6 Mon Sep 17 00:00:00 2001 From: Martin Ashby Date: Sun, 18 Feb 2024 20:28:55 +0000 Subject: Add CGI handling to my basic server Fix some missing bits from the comments CGI program, specifically - respect content_length from the web server - write the http status response as a header in the result --- comments/src/main.zig | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) (limited to 'comments') diff --git a/comments/src/main.zig b/comments/src/main.zig index ac8193e..4044ae7 100644 --- a/comments/src/main.zig +++ b/comments/src/main.zig @@ -35,6 +35,8 @@ const Err = error{ SystemResources, Unexpected, WouldBlock, + Overflow, + EndOfStream, }; const Ctx = struct { db: pq.Db, @@ -80,13 +82,19 @@ const Response = struct { return std.io.getStdIn().reader(); } fn do(self: @This()) !void { + const wtr = std.io.getStdOut().writer(); + if (self.status.phrase()) |phrase| { + try std.fmt.format(wtr, "status: {} {s}\r\n", .{@intFromEnum(self.status), phrase}); + } else { + try std.fmt.format(wtr, "status: {}\r\n", .{@intFromEnum(self.status)}); + } 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 wtr.writeAll(tup.key); + try wtr.writeAll(": "); + try wtr.writeAll(tup.val); + try wtr.writeAll("\r\n"); } - try std.io.getStdOut().writeAll("\r\n"); + try wtr.writeAll("\r\n"); } fn writer(_: @This()) std.fs.File.Writer { return std.io.getStdOut().writer(); @@ -136,7 +144,7 @@ pub fn main() !void { var res = Response{ .allocator = allocator, .request = req, - .status = .bad_request, + .status = .ok, .transfer_encoding = .none, .headers = Headers.init(allocator), }; @@ -203,9 +211,12 @@ fn get_comment(res: *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); - const body = try body_aa.toOwnedSlice(); + const cl = if (std.os.getenv("CONTENT_LENGTH")) |clh| try std.fmt.parseInt(usize, clh, 10) else { + return error.InvalidLength; + }; + const body = try res.allocator.alloc(u8, cl); + defer res.allocator.free(body); + try res.reader().readNoEof(body); var form = try zws.Form.parse(res.allocator, body); const Form = struct { url: []const u8, @@ -215,6 +226,7 @@ fn post_comment(res: *Response, ctx: Ctx, _: Params) Err!void { capcha_answer: []const u8, }; const form_val = form.form_to_struct(Form) catch { + std.log.err("couldn't parse Form", .{}); try badrequest(res, ctx); return; }; @@ -231,6 +243,7 @@ fn post_comment(res: *Response, ctx: Ctx, _: Params) Err!void { } const ans = try stmt.read_column(0, []const u8); if (!std.mem.eql(u8, ans, form_val.capcha_answer)) { + std.log.err("bad capcha answer {s} expected {s}", .{form_val.capcha_answer, ans}); try constresponse(res, @embedFile("templates/capchainvalid.html"), std.http.Status.unauthorized); return; } -- cgit v1.2.3-ZIG