mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
+10
-6
@@ -1133,7 +1133,16 @@ pub const Request = struct {
|
||||
pub fn receiveHead(r: *Request, redirect_buffer: []u8) ReceiveHeadError!Response {
|
||||
var aux_buf = redirect_buffer;
|
||||
while (true) {
|
||||
const head_buffer = try r.reader.receiveHead();
|
||||
// This while loop is for handling redirects, which means the request's
|
||||
// connection may be different than the previous iteration. However, it
|
||||
// is still guaranteed to be non-null with each iteration of this loop.
|
||||
const connection = r.connection.?;
|
||||
|
||||
const head_buffer = r.reader.receiveHead() catch |err| {
|
||||
// Failure here means the connection can no longer be reused.
|
||||
connection.closing = true;
|
||||
return err;
|
||||
};
|
||||
const response: Response = .{
|
||||
.request = r,
|
||||
.head = Response.Head.parse(head_buffer) catch return error.HttpHeadersInvalid,
|
||||
@@ -1147,11 +1156,6 @@ pub const Request = struct {
|
||||
return response; // we're not handling the 100-continue
|
||||
}
|
||||
|
||||
// This while loop is for handling redirects, which means the request's
|
||||
// connection may be different than the previous iteration. However, it
|
||||
// is still guaranteed to be non-null with each iteration of this loop.
|
||||
const connection = r.connection.?;
|
||||
|
||||
if (r.method == .CONNECT and head.status.class() == .success) {
|
||||
// This connection is no longer doing HTTP.
|
||||
connection.closing = false;
|
||||
|
||||
@@ -1256,3 +1256,63 @@ test "redirect to different connection" {
|
||||
try expectEqualStrings("good job, you pass", body);
|
||||
}
|
||||
}
|
||||
|
||||
test "boot failed connections from the pool" {
|
||||
if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171879
|
||||
if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806
|
||||
|
||||
const io = std.testing.io;
|
||||
const gpa = std.testing.allocator;
|
||||
|
||||
const test_server_orig = try createTestServer(io, struct {
|
||||
fn run(test_server: *TestServer) anyerror!void {
|
||||
const net_server = &test_server.net_server;
|
||||
var recv_buffer: [500]u8 = undefined;
|
||||
var send_buffer: [500]u8 = undefined;
|
||||
|
||||
accept: while (!test_server.shutting_down) {
|
||||
var stream = try net_server.accept(io);
|
||||
defer stream.close(io);
|
||||
|
||||
for (0..2) |i| {
|
||||
var connection_br = stream.reader(io, &recv_buffer);
|
||||
var connection_bw = stream.writer(io, &send_buffer);
|
||||
var server = http.Server.init(&connection_br.interface, &connection_bw.interface);
|
||||
var request = server.receiveHead() catch |err| switch (err) {
|
||||
error.HttpConnectionClosing => continue :accept,
|
||||
else => |e| return e,
|
||||
};
|
||||
if (i == 0) try request.respond("hello", .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
defer test_server_orig.destroy();
|
||||
|
||||
var client: http.Client = .{
|
||||
.allocator = gpa,
|
||||
.io = io,
|
||||
};
|
||||
defer client.deinit();
|
||||
|
||||
var loc_buf: [100]u8 = undefined;
|
||||
const location = try std.fmt.bufPrint(&loc_buf, "http://127.0.0.1:{d}/", .{
|
||||
test_server_orig.port(),
|
||||
});
|
||||
const uri = try std.Uri.parse(location);
|
||||
|
||||
{
|
||||
const response = try client.fetch(.{ .location = .{ .uri = uri } });
|
||||
try expectEqual(.ok, response.status);
|
||||
}
|
||||
{
|
||||
try expectError(error.HttpConnectionClosing, client.fetch(.{ .location = .{ .uri = uri } }));
|
||||
}
|
||||
{
|
||||
const response = try client.fetch(.{ .location = .{ .uri = uri } });
|
||||
try expectEqual(.ok, response.status);
|
||||
}
|
||||
{
|
||||
try expectError(error.HttpConnectionClosing, client.fetch(.{ .location = .{ .uri = uri } }));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user