| ... | @@ -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. |
| 602 | | 602 | |
| 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 | } |
| 628 | | 628 | |
| 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; |
| 631 | | 631 | |
| 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 | } |
| 641 | | 641 | |
| ... | @@ -748,7 +748,7 @@ pub const Request = struct { | ... | @@ -748,7 +748,7 @@ pub const Request = struct { |
| 748 | } | 748 | } |
| 749 | } | 749 | } |
| 750 | | 750 | |
| 751 | pub const ReadError = TransferReadError; | 751 | pub const ReadError = TransferReadError || proto.HeadersParser.CheckCompleteHeadError; |
| 752 | | 752 | |
| 753 | pub const Reader = std.io.Reader(*Request, ReadError, read); | 753 | pub const Reader = std.io.Reader(*Request, ReadError, read); |
| 754 | | 754 | |
| ... | @@ -758,26 +758,40 @@ pub const Request = struct { | ... | @@ -758,26 +758,40 @@ pub const Request = struct { |
| 758 | | 758 | |
| 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 | }; |
| 762 | | 780 | |
| 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 | } |
| 782 | | 796 | |
| 783 | /// Reads data from the response body. Must be called after `do`. | 797 | /// Reads data from the response body. Must be called after `do`. |