An HTTP/1.1 server for zig
0

Configure Feed

Select the types of activity you want to include in your feed.

Zig 0.15 support

+44 -52
+8 -3
build.zig
··· 75 75 for (examples) |ex| { 76 76 const exe = b.addExecutable(.{ 77 77 .name = ex.name, 78 - .root_module = httpz_module, 78 + .root_module = b.createModule(.{ 79 + .root_source_file = b.path(ex.file), 80 + .target = target, 81 + .optimize = optimize, 82 + .imports = &.{ 83 + .{.name = "httpz", .module = httpz_module}, 84 + } 85 + }), 79 86 }); 80 - exe.root_module.addImport("httpz", httpz_module); 81 - exe.root_module.addImport("metrics", metrics_module); 82 87 if (ex.libc) { 83 88 exe.linkLibC(); 84 89 }
+2 -2
build.zig.zon
··· 9 9 .hash = "metrics-0.0.0-W7G4eP2_AQBKsaql3dhLJ-pkf-RdP-zV3vflJy4N34jC", 10 10 }, 11 11 .websocket = .{ 12 - .url = "https://github.com/karlseguin/websocket.zig/archive/0960332e63793eef3815279165538b8b7458bc95.tar.gz", 13 - .hash = "websocket-0.1.0-ZPISddFYAwBths--HBSm3ROmy78ZaOvHl7ttdfq_6wfk", 12 + .url = "https://github.com/karlseguin/websocket.zig/archive/59aaa71e64a669aa90016f8a342ceeee6381b4a6.tar.gz", 13 + .hash = "websocket-0.1.0-ZPISdYluAwBl2ckLPQ_q5_1IPEmNmaJ9vU1V0ap1-_dD", 14 14 }, 15 15 // .websocket = .{ .path = "../websocket.zig" }, 16 16 },
+5 -10
src/httpz.zig
··· 685 685 686 686 hc.handler = try H.init(&hc.conn, ctx); 687 687 688 - var agreed_compression: ?websocket.Compression = null; 688 + var compression = false; 689 689 if (ws_worker.canCompress()) { 690 690 if (req.header("sec-websocket-extensions")) |ext| { 691 - if (try websocket.Handshake.parseExtension(ext)) |request_compression| { 692 - agreed_compression = .{ 693 - .client_no_context_takeover = request_compression.client_no_context_takeover, 694 - .server_no_context_takeover = request_compression.server_no_context_takeover, 695 - }; 696 - } 691 + compression = try websocket.Handshake.parseExtension(ext) != null; 697 692 } 698 693 } 699 694 700 695 var reply_buf: [512]u8 = undefined; 701 - const reply = try websocket.Handshake.createReply(key, null, agreed_compression, &reply_buf); 696 + const reply = try websocket.Handshake.createReply(key, null, compression, &reply_buf); 702 697 try http_conn.stream.writeAll(reply); 703 698 if (comptime std.meta.hasFn(H, "afterInit")) { 704 699 const params = @typeInfo(@TypeOf(H.afterInit)).@"fn".params; 705 700 try if (comptime params.len == 1) hc.handler.?.afterInit() else hc.handler.?.afterInit(ctx); 706 701 } 707 - try ws_worker.setupConnection(hc, agreed_compression); 702 + try ws_worker.setupConnection(hc); 708 703 res.written = true; 709 704 http_conn.handover = .{ .websocket = hc }; 710 705 return true; ··· 1736 1731 var aw: std.io.Writer.Allocating = .init(res.arena); 1737 1732 try json_writer.format(&aw.writer); 1738 1733 1739 - res.body = aw.getWritten(); 1734 + res.body = aw.written(); 1740 1735 return res.write(); 1741 1736 } 1742 1737
+1 -1
src/request.zig
··· 1839 1839 aw.writer.writeAll(b) catch unreachable; 1840 1840 } 1841 1841 1842 - return aw.getWritten(); 1842 + return aw.written(); 1843 1843 }
+3 -3
src/router.zig
··· 210 210 normalized = normalized[0 .. normalized.len - 1]; 211 211 } 212 212 213 - var param_name_collector = std.ArrayList([]const u8).init(allocator); 214 - defer param_name_collector.deinit(); 213 + var param_name_collector: std.ArrayList([]const u8) = .empty; 214 + defer param_name_collector.deinit(allocator); 215 215 216 216 var route_part = root; 217 217 var it = std.mem.splitScalar(u8, normalized, '/'); 218 218 while (it.next()) |part| { 219 219 if (part[0] == ':') { 220 - try param_name_collector.append(part[1..]); 220 + try param_name_collector.append(allocator, part[1..]); 221 221 if (route_part.param_part) |child| { 222 222 route_part = child; 223 223 } else {
+4 -12
src/t.zig
··· 125 125 ._io_mode = if (httpz.blockingMode()) .blocking else .nonblocking, 126 126 }; 127 127 128 - return .{ 129 - .conn = conn, 130 - .arena = ctx_arena, 131 - .stream = server, 132 - .client = client, 133 - .fake = false, 134 - .to_read_pos = 0, 135 - .to_read = std.ArrayList(u8).init(aa), 136 - }; 128 + return .{ .conn = conn, .arena = ctx_arena, .stream = server, .client = client, .fake = false, .to_read_pos = 0, .to_read = .empty }; 137 129 } 138 130 139 131 pub fn init(config: httpz.Config) Context { ··· 186 178 187 179 pub fn write(self: *Context, data: []const u8) void { 188 180 if (self.fake) { 189 - self.to_read.appendSlice(data) catch unreachable; 181 + self.to_read.appendSlice(self.arena.allocator(), data) catch unreachable; 190 182 } else { 191 183 self.client.writeAll(data) catch unreachable; 192 184 } ··· 194 186 195 187 pub fn read(self: Context, a: Allocator) !std.ArrayList(u8) { 196 188 var buf: [1024]u8 = undefined; 197 - var arr = std.ArrayList(u8).init(a); 189 + var arr: std.ArrayList(u8) = .empty; 198 190 199 191 while (true) { 200 192 const n = self.client.read(&buf) catch |err| switch (err) { ··· 202 194 else => return err, 203 195 }; 204 196 if (n == 0) return arr; 205 - try arr.appendSlice(buf[0..n]); 197 + try arr.appendSlice(a, buf[0..n]); 206 198 } 207 199 unreachable; 208 200 }
+21 -21
src/testing.zig
··· 144 144 var aw: std.Io.Writer.Allocating = .init(self.arena); 145 145 json_writer.format(&aw.writer) catch unreachable; 146 146 147 - self.req.body_buffer = .{ .type = .static, .data = aw.getWritten() }; 148 - self.req.body_len = aw.getWritten().len; 147 + self.req.body_buffer = .{ .type = .static, .data = aw.written() }; 148 + self.req.body_len = aw.written().len; 149 149 } 150 150 151 151 pub fn form(self: *Testing, data: anytype) void { 152 - var arr = ArrayList(u8).init(self.arena); 152 + var arr: ArrayList(u8) = .empty; 153 153 154 154 inline for (@typeInfo(@TypeOf(data)).@"struct".fields) |field| { 155 155 const name = escapeString(self.arena, field.name) catch unreachable; 156 156 const value = escapeString(self.arena, @field(data, field.name)) catch unreachable; 157 - arr.appendSlice(name) catch unreachable; 158 - arr.append('=') catch unreachable; 159 - arr.appendSlice(value) catch unreachable; 160 - arr.append('&') catch unreachable; 157 + arr.appendSlice(self.arena, name) catch unreachable; 158 + arr.append(self.arena, '=') catch unreachable; 159 + arr.appendSlice(self.arena, value) catch unreachable; 160 + arr.append(self.arena, '&') catch unreachable; 161 161 } 162 162 163 163 const items = arr.items; ··· 401 401 const json_writer = std.json.fmt(b_value, .{ .whitespace = .indent_2 }); 402 402 var aw: std.Io.Writer.Allocating = .init(allocator); 403 403 try json_writer.format(&aw.writer); 404 - self.pretty_actual = aw.getWritten(); 404 + self.pretty_actual = aw.written(); 405 405 406 - var diffs = ArrayList(Diff).init(allocator); 407 - var path = ArrayList([]const u8).init(allocator); 406 + var diffs: ArrayList(Diff) = .empty; 407 + var path: ArrayList([]const u8) = .empty; 408 408 try self.compareValue(a_value, b_value, &diffs, &path); 409 409 return diffs; 410 410 } ··· 413 413 const allocator = self._arena.allocator(); 414 414 415 415 if (!std.mem.eql(u8, @tagName(a), @tagName(b))) { 416 - diffs.append(self.diff("types don't match", path, @tagName(a), @tagName(b))) catch unreachable; 416 + diffs.append(allocator, self.diff("types don't match", path, @tagName(a), @tagName(b))) catch unreachable; 417 417 return; 418 418 } 419 419 ··· 421 421 .null => {}, 422 422 .bool => { 423 423 if (a.bool != b.bool) { 424 - diffs.append(self.diff("not equal", path, self.format(a.bool), self.format(b.bool))) catch unreachable; 424 + diffs.append(allocator, self.diff("not equal", path, self.format(a.bool), self.format(b.bool))) catch unreachable; 425 425 } 426 426 }, 427 427 .integer => { 428 428 if (a.integer != b.integer) { 429 - diffs.append(self.diff("not equal", path, self.format(a.integer), self.format(b.integer))) catch unreachable; 429 + diffs.append(allocator, self.diff("not equal", path, self.format(a.integer), self.format(b.integer))) catch unreachable; 430 430 } 431 431 }, 432 432 .float => { 433 433 if (a.float != b.float) { 434 - diffs.append(self.diff("not equal", path, self.format(a.float), self.format(b.float))) catch unreachable; 434 + diffs.append(allocator, self.diff("not equal", path, self.format(a.float), self.format(b.float))) catch unreachable; 435 435 } 436 436 }, 437 437 .number_string => { 438 438 if (!std.mem.eql(u8, a.number_string, b.number_string)) { 439 - diffs.append(self.diff("not equal", path, a.number_string, b.number_string)) catch unreachable; 439 + diffs.append(allocator, self.diff("not equal", path, a.number_string, b.number_string)) catch unreachable; 440 440 } 441 441 }, 442 442 .string => { 443 443 if (!std.mem.eql(u8, a.string, b.string)) { 444 - diffs.append(self.diff("not equal", path, a.string, b.string)) catch unreachable; 444 + diffs.append(allocator, self.diff("not equal", path, a.string, b.string)) catch unreachable; 445 445 } 446 446 }, 447 447 .array => { 448 448 const a_len = a.array.items.len; 449 449 const b_len = b.array.items.len; 450 450 if (a_len != b_len) { 451 - diffs.append(self.diff("array length", path, self.format(a_len), self.format(b_len))) catch unreachable; 451 + diffs.append(allocator, self.diff("array length", path, self.format(a_len), self.format(b_len))) catch unreachable; 452 452 return; 453 453 } 454 454 for (a.array.items, b.array.items, 0..) |a_item, b_item, i| { 455 - try path.append(try std.fmt.allocPrint(allocator, "{d}", .{i})); 455 + try path.append(allocator, try std.fmt.allocPrint(allocator, "{d}", .{i})); 456 456 try self.compareValue(a_item, b_item, diffs, path); 457 457 _ = path.pop(); 458 458 } ··· 461 461 var it = a.object.iterator(); 462 462 while (it.next()) |entry| { 463 463 const key = entry.key_ptr.*; 464 - try path.append(key); 464 + try path.append(allocator, key); 465 465 if (b.object.get(key)) |b_item| { 466 466 try self.compareValue(entry.value_ptr.*, b_item, diffs, path); 467 467 } else { 468 - diffs.append(self.diff("field missing", path, key, "")) catch unreachable; 468 + diffs.append(allocator, self.diff("field missing", path, key, "")) catch unreachable; 469 469 } 470 470 _ = path.pop(); 471 471 } ··· 487 487 var aw: std.io.Writer.Allocating = .init(self._arena.allocator()); 488 488 const json_writer = std.json.fmt(value, .{}); 489 489 try json_writer.format(&aw.writer); 490 - return aw.getWritten(); 490 + return aw.written(); 491 491 } 492 492 493 493 fn format(self: *JsonComparer, value: anytype) []const u8 {