authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-18 17:22:56-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-08-18 17:26:55-07:00
log89c9282d346498e1b3ca9dfe26bf776311cd0ded
treeb3639864b9545ef68662ad16dbaf9a37fa0af593
parentb734d03340c0b120a7f6376000714b9765c5dbcc

std.http.Client: discard response body when reusing connection

When an error response was encountered, such as 404 not found, the body wasn't discarded, leading to the string "404 not found" being incorrectly interpreted as the next request's response. closes #24732

1 files changed, 24 insertions(+), 1 deletions(-)

lib/std/http/Client.zig+24-1
...@@ -787,6 +787,13 @@ pub const Request = struct {...@@ -787,6 +787,13 @@ pub const Request = struct {
787 /// Standard headers that have default, but overridable, behavior.787 /// Standard headers that have default, but overridable, behavior.
788 headers: Headers,788 headers: Headers,
789789
790 /// Populated in `receiveHead`; used in `deinit` to determine whether to
791 /// discard the body to reuse the connection.
792 response_content_length: ?u64 = null,
793 /// Populated in `receiveHead`; used in `deinit` to determine whether to
794 /// discard the body to reuse the connection.
795 response_transfer_encoding: http.TransferEncoding = .none,
796
790 /// These headers are kept including when following a redirect to a797 /// These headers are kept including when following a redirect to a
791 /// different domain.798 /// different domain.
792 /// Externally-owned; must outlive the Request.799 /// Externally-owned; must outlive the Request.
...@@ -860,7 +867,15 @@ pub const Request = struct {...@@ -860,7 +867,15 @@ pub const Request = struct {
860 if (r.connection) |connection| {867 if (r.connection) |connection| {
861 connection.closing = connection.closing or switch (r.reader.state) {868 connection.closing = connection.closing or switch (r.reader.state) {
862 .ready => false,869 .ready => false,
863 .received_head => r.method.requestHasBody(),870 .received_head => c: {
871 if (r.method.requestHasBody()) break :c true;
872 if (!r.method.responseHasBody()) break :c false;
873 const reader = r.reader.bodyReader(&.{}, r.response_transfer_encoding, r.response_content_length);
874 _ = reader.discardRemaining() catch |err| switch (err) {
875 error.ReadFailed => break :c true,
876 };
877 break :c r.reader.state != .ready;
878 },
864 else => true,879 else => true,
865 };880 };
866 r.client.connection_pool.release(connection);881 r.client.connection_pool.release(connection);
...@@ -1102,6 +1117,8 @@ pub const Request = struct {...@@ -1102,6 +1117,8 @@ pub const Request = struct {
11021117
1103 if (head.status == .@"continue") {1118 if (head.status == .@"continue") {
1104 if (r.handle_continue) continue;1119 if (r.handle_continue) continue;
1120 r.response_transfer_encoding = head.transfer_encoding;
1121 r.response_content_length = head.content_length;
1105 return response; // we're not handling the 100-continue1122 return response; // we're not handling the 100-continue
1106 }1123 }
11071124
...@@ -1113,6 +1130,8 @@ pub const Request = struct {...@@ -1113,6 +1130,8 @@ pub const Request = struct {
1113 if (r.method == .CONNECT and head.status.class() == .success) {1130 if (r.method == .CONNECT and head.status.class() == .success) {
1114 // This connection is no longer doing HTTP.1131 // This connection is no longer doing HTTP.
1115 connection.closing = false;1132 connection.closing = false;
1133 r.response_transfer_encoding = head.transfer_encoding;
1134 r.response_content_length = head.content_length;
1116 return response;1135 return response;
1117 }1136 }
11181137
...@@ -1126,6 +1145,8 @@ pub const Request = struct {...@@ -1126,6 +1145,8 @@ pub const Request = struct {
1126 if (r.method == .HEAD or head.status.class() == .informational or1145 if (r.method == .HEAD or head.status.class() == .informational or
1127 head.status == .no_content or head.status == .not_modified)1146 head.status == .no_content or head.status == .not_modified)
1128 {1147 {
1148 r.response_transfer_encoding = head.transfer_encoding;
1149 r.response_content_length = head.content_length;
1129 return response;1150 return response;
1130 }1151 }
11311152
...@@ -1146,6 +1167,8 @@ pub const Request = struct {...@@ -1146,6 +1167,8 @@ pub const Request = struct {
1146 if (!r.accept_encoding[@intFromEnum(head.content_encoding)])1167 if (!r.accept_encoding[@intFromEnum(head.content_encoding)])
1147 return error.HttpContentEncodingUnsupported;1168 return error.HttpContentEncodingUnsupported;
11481169
1170 r.response_transfer_encoding = head.transfer_encoding;
1171 r.response_content_length = head.content_length;
1149 return response;1172 return response;
1150 }1173 }
1151 }1174 }