authorgravatar for truemedian@gmail.comNameless <truemedian@gmail.com> 2024-01-14 21:26:27-06:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-18 15:43:58-08:00
loga7dbc57a35ee4695883f540e1d3a9d00506cf7bc
tree02487c6610a51d49551aab033f53fa550ae87ff8
parent22b9d8987dd667842de0b6848043a2bd53864569

std.http.Client: read response messages with no length until eof


2 files changed, 18 insertions(+), 11 deletions(-)

lib/std/http/Client.zig+15-8
...@@ -821,13 +821,15 @@ pub const Request = struct {...@@ -821,13 +821,15 @@ pub const Request = struct {
821 if (req.handle_continue)821 if (req.handle_continue)
822 continue;822 continue;
823823
824 break;824 return; // we're not handling the 100-continue, return to the caller
825 }825 }
826826
827 // we're switching protocols, so this connection is no longer doing http827 // we're switching protocols, so this connection is no longer doing http
828 if (req.response.status == .switching_protocols or (req.method == .CONNECT and req.response.status == .ok)) {828 if (req.method == .CONNECT and req.response.status.class() == .success) {
829 req.connection.?.closing = false;829 req.connection.?.closing = false;
830 req.response.parser.done = true;830 req.response.parser.done = true;
831
832 return; // the connection is not HTTP past this point, return to the caller
831 }833 }
832834
833 // we default to using keep-alive if not provided in the client if the server asks for it835 // we default to using keep-alive if not provided in the client if the server asks for it
...@@ -842,6 +844,15 @@ pub const Request = struct {...@@ -842,6 +844,15 @@ pub const Request = struct {
842 req.connection.?.closing = true;844 req.connection.?.closing = true;
843 }845 }
844846
847 // Any response to a HEAD request and any response with a 1xx (Informational), 204 (No Content), or 304 (Not Modified)
848 // status code is always terminated by the first empty line after the header fields, regardless of the header fields
849 // present in the message
850 if (req.method == .HEAD or req.response.status.class() == .informational or req.response.status == .no_content or req.response.status == .not_modified) {
851 req.response.parser.done = true;
852
853 return; // the response is empty, no further setup or redirection is necessary
854 }
855
845 if (req.response.transfer_encoding != .none) {856 if (req.response.transfer_encoding != .none) {
846 switch (req.response.transfer_encoding) {857 switch (req.response.transfer_encoding) {
847 .none => unreachable,858 .none => unreachable,
...@@ -855,12 +866,8 @@ pub const Request = struct {...@@ -855,12 +866,8 @@ pub const Request = struct {
855866
856 if (cl == 0) req.response.parser.done = true;867 if (cl == 0) req.response.parser.done = true;
857 } else {868 } else {
858 req.response.parser.done = true;869 // read until the connection is closed
859 }870 req.response.parser.next_chunk_length = std.math.maxInt(u64);
860
861 // HEAD requests have no body
862 if (req.method == .HEAD) {
863 req.response.parser.done = true;
864 }871 }
865872
866 if (req.response.status.class() == .redirect and req.handle_redirects) {873 if (req.response.status.class() == .redirect and req.handle_redirects) {
lib/std/http/protocol.zig+3-3
...@@ -524,7 +524,7 @@ pub const HeadersParser = struct {...@@ -524,7 +524,7 @@ pub const HeadersParser = struct {
524 ///524 ///
525 /// If `skip` is true, the buffer will be unused and the body will be skipped.525 /// If `skip` is true, the buffer will be unused and the body will be skipped.
526 ///526 ///
527 /// See `std.http.Client.BufferedConnection for an example of `conn`.527 /// See `std.http.Client.Connection for an example of `conn`.
528 pub fn read(r: *HeadersParser, conn: anytype, buffer: []u8, skip: bool) !usize {528 pub fn read(r: *HeadersParser, conn: anytype, buffer: []u8, skip: bool) !usize {
529 assert(r.state.isContent());529 assert(r.state.isContent());
530 if (r.done) return 0;530 if (r.done) return 0;
...@@ -543,7 +543,7 @@ pub const HeadersParser = struct {...@@ -543,7 +543,7 @@ pub const HeadersParser = struct {
543 conn.drop(@intCast(nread));543 conn.drop(@intCast(nread));
544 r.next_chunk_length -= nread;544 r.next_chunk_length -= nread;
545545
546 if (r.next_chunk_length == 0) r.done = true;546 if (r.next_chunk_length == 0 or nread == 0) r.done = true;
547547
548 return out_index;548 return out_index;
549 } else if (out_index < buffer.len) {549 } else if (out_index < buffer.len) {
...@@ -553,7 +553,7 @@ pub const HeadersParser = struct {...@@ -553,7 +553,7 @@ pub const HeadersParser = struct {
553 const nread = try conn.read(buffer[0..can_read]);553 const nread = try conn.read(buffer[0..can_read]);
554 r.next_chunk_length -= nread;554 r.next_chunk_length -= nread;
555555
556 if (r.next_chunk_length == 0) r.done = true;556 if (r.next_chunk_length == 0 or nread == 0) r.done = true;
557557
558 return nread;558 return nread;
559 } else {559 } else {