authorgravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2023-04-03 16:21:54-05:00
committergravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2023-04-08 09:59:36-05:00
log8250a925444254c6c0c84af3006d04b7102a3343
tree151a69a2a467c5dfbbcd1e0d6a44b3e0aed28a8e
parent52c78f4974d1913b9b7af678377a4c76a41ae23f
signaturelock-open Commit is signed but in an unrecognized format.

update package manager to use req.do(), fix chunked trailer reading


2 files changed, 39 insertions(+), 23 deletions(-)

lib/std/http/Client.zig+37-23
...@@ -598,7 +598,7 @@ pub const Request = struct {...@@ -598,7 +598,7 @@ pub const Request = struct {
598 try w.writeAll("\r\nConnection: keep-alive");598 try w.writeAll("\r\nConnection: keep-alive");
599 }599 }
600 try w.writeAll("\r\nAccept-Encoding: gzip, deflate, zstd");600 try w.writeAll("\r\nAccept-Encoding: gzip, deflate, zstd");
601 try w.writeAll("\r\nTE: trailers, gzip, deflate");601 try w.writeAll("\r\nTE: gzip, deflate"); // TODO: add trailers when someone finds a nice way to integrate them without completely invalidating all pointers to headers.
602602
603 switch (headers.transfer_encoding) {603 switch (headers.transfer_encoding) {
604 .chunked => try w.writeAll("\r\nTransfer-Encoding: chunked"),604 .chunked => try w.writeAll("\r\nTransfer-Encoding: chunked"),
...@@ -627,7 +627,7 @@ pub const Request = struct {...@@ -627,7 +627,7 @@ pub const Request = struct {
627 }627 }
628628
629 pub fn transferRead(req: *Request, buf: []u8) TransferReadError!usize {629 pub fn transferRead(req: *Request, buf: []u8) TransferReadError!usize {
630 if (req.response.parser.isComplete()) return 0;630 if (req.response.parser.done) return 0;
631631
632 var index: usize = 0;632 var index: usize = 0;
633 while (index == 0) {633 while (index == 0) {
...@@ -635,7 +635,7 @@ pub const Request = struct {...@@ -635,7 +635,7 @@ pub const Request = struct {
635 req.client.last_error = .{ .read = err };635 req.client.last_error = .{ .read = err };
636 return error.ReadFailed;636 return error.ReadFailed;
637 };637 };
638 if (amt == 0 and req.response.parser.isComplete()) break;638 if (amt == 0 and req.response.parser.done) break;
639 index += amt;639 index += amt;
640 }640 }
641641
...@@ -748,7 +748,7 @@ pub const Request = struct {...@@ -748,7 +748,7 @@ pub const Request = struct {
748 }748 }
749 }749 }
750750
751 pub const ReadError = TransferReadError;751 pub const ReadError = TransferReadError || proto.HeadersParser.CheckCompleteHeadError;
752752
753 pub const Reader = std.io.Reader(*Request, ReadError, read);753 pub const Reader = std.io.Reader(*Request, ReadError, read);
754754
...@@ -758,26 +758,40 @@ pub const Request = struct {...@@ -758,26 +758,40 @@ pub const Request = struct {
758758
759 /// Reads data from the response body. Must be called after `do`.759 /// Reads data from the response body. Must be called after `do`.
760 pub fn read(req: *Request, buffer: []u8) ReadError!usize {760 pub fn read(req: *Request, buffer: []u8) ReadError!usize {
761 assert(req.response.parser.state.isContent());761 while (true) {
762 const out_index = switch (req.response.compression) {
763 .deflate => |*deflate| deflate.read(buffer) catch |err| {
764 req.client.last_error = .{ .decompress = err };
765 err catch {};
766 return error.ReadFailed;
767 },
768 .gzip => |*gzip| gzip.read(buffer) catch |err| {
769 req.client.last_error = .{ .decompress = err };
770 err catch {};
771 return error.ReadFailed;
772 },
773 .zstd => |*zstd| zstd.read(buffer) catch |err| {
774 req.client.last_error = .{ .decompress = err };
775 err catch {};
776 return error.ReadFailed;
777 },
778 else => try req.transferRead(buffer),
779 };
762780
763 return switch (req.response.compression) {781 if (out_index == 0) {
764 .deflate => |*deflate| deflate.read(buffer) catch |err| {782 while (!req.response.parser.state.isContent()) { // read trailing headers
765 req.client.last_error = .{ .decompress = err };783 req.connection.data.buffered.fill() catch |err| {
766 err catch {};784 req.client.last_error = .{ .read = err };
767 return error.ReadFailed;785 return error.ReadFailed;
768 },786 };
769 .gzip => |*gzip| gzip.read(buffer) catch |err| {787
770 req.client.last_error = .{ .decompress = err };788 const nchecked = try req.response.parser.checkCompleteHead(req.client.allocator, req.connection.data.buffered.peek());
771 err catch {};789 req.connection.data.buffered.clear(@intCast(u16, nchecked));
772 return error.ReadFailed;790 }
773 },791 }
774 .zstd => |*zstd| zstd.read(buffer) catch |err| {792
775 req.client.last_error = .{ .decompress = err };793 return out_index;
776 err catch {};794 }
777 return error.ReadFailed;
778 },
779 else => try req.transferRead(buffer),
780 };
781 }795 }
782796
783 /// Reads data from the response body. Must be called after `do`.797 /// Reads data from the response body. Must be called after `do`.
src/Package.zig+2
...@@ -482,6 +482,8 @@ fn fetchAndUnpack(...@@ -482,6 +482,8 @@ fn fetchAndUnpack(
482 var req = try http_client.request(uri, .{}, .{});482 var req = try http_client.request(uri, .{}, .{});
483 defer req.deinit();483 defer req.deinit();
484484
485 try req.do();
486
485 if (mem.endsWith(u8, uri.path, ".tar.gz")) {487 if (mem.endsWith(u8, uri.path, ".tar.gz")) {
486 // I observed the gzip stream to read 1 byte at a time, so I am using a488 // I observed the gzip stream to read 1 byte at a time, so I am using a
487 // buffered reader on the front of it.489 // buffered reader on the front of it.