Skip to content

Commit 8033e41

Browse files
authored
Merge pull request #788 from lightpanda-io/dont_keepalive_unprocess_request
Delay setting the requests' keepalive flag until the request is fully…
2 parents 60f4eab + a6ac7d9 commit 8033e41

File tree

1 file changed

+15
-17
lines changed

1 file changed

+15
-17
lines changed

src/http/client.zig

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ pub const Request = struct {
716716
}
717717

718718
fn newReader(self: *Request) Reader {
719-
return Reader.init(self._state, &self._keepalive);
719+
return Reader.init(self._state);
720720
}
721721

722722
// Does additional setup of the request for the firsts (i.e. non-redirect) call.
@@ -879,12 +879,14 @@ pub const Request = struct {
879879
});
880880
}
881881

882-
fn requestCompleted(self: *Request, response: ResponseHeader) void {
882+
fn requestCompleted(self: *Request, response: ResponseHeader, can_keepalive: bool) void {
883883
const notification = self.notification orelse return;
884884
if (self._notified_complete) {
885885
return;
886886
}
887+
887888
self._notified_complete = true;
889+
self._keepalive = can_keepalive;
888890
notification.dispatch(.http_request_complete, &.{
889891
.id = self.id,
890892
.url = self.request_uri,
@@ -1111,14 +1113,14 @@ fn AsyncHandler(comptime H: type, comptime L: type) type {
11111113
.handler_error => {
11121114
// handler should never have been called if we're redirecting
11131115
std.debug.assert(self.redirect == null);
1114-
self.request.requestCompleted(self.reader.response);
1116+
self.request.requestCompleted(self.reader.response, self.reader.keepalive);
11151117
self.deinit();
11161118
return;
11171119
},
11181120
.done => {
11191121
const redirect = self.redirect orelse {
11201122
var handler = self.handler;
1121-
self.request.requestCompleted(self.reader.response);
1123+
self.request.requestCompleted(self.reader.response, self.reader.keepalive);
11221124
self.deinit();
11231125

11241126
// Emit the done chunk. We expect the caller to do
@@ -1560,8 +1562,6 @@ const SyncHandler = struct {
15601562
var decompressor = std.compress.gzip.decompressor(compress_reader.reader());
15611563
try decompressor.decompress(body.writer(request.arena));
15621564

1563-
self.request.requestCompleted(reader.response);
1564-
15651565
return .{
15661566
.header = reader.response,
15671567
._done = true,
@@ -1781,8 +1781,8 @@ const SyncHandler = struct {
17811781

17821782
// Used for reading the response (both the header and the body)
17831783
const Reader = struct {
1784-
// ref request.keepalive
1785-
keepalive: *bool,
1784+
// Wether, from the reader's point of view, this connection could be kept-alive
1785+
keepalive: bool,
17861786

17871787
// always references state.header_buf
17881788
header_buf: []u8,
@@ -1802,13 +1802,13 @@ const Reader = struct {
18021802
// Whether or not the current header has to be skipped [because it's too long].
18031803
skip_current_header: bool,
18041804

1805-
fn init(state: *State, keepalive: *bool) Reader {
1805+
fn init(state: *State) Reader {
18061806
return .{
18071807
.pos = 0,
18081808
.response = .{},
18091809
.body_reader = null,
18101810
.header_done = false,
1811-
.keepalive = keepalive,
1811+
.keepalive = false,
18121812
.skip_current_header = false,
18131813
.header_buf = state.header_buf,
18141814
.arena = state.arena.allocator(),
@@ -1835,7 +1835,6 @@ const Reader = struct {
18351835
// us to emit whatever data we have, but it isn't safe to keep
18361836
// the connection alive.
18371837
std.debug.assert(result.done == true);
1838-
self.keepalive.* = false;
18391838
}
18401839
return result;
18411840
}
@@ -1930,7 +1929,7 @@ const Reader = struct {
19301929
// We think we're done reading the body, but we still have data
19311930
// We'll return what we have as-is, but close the connection
19321931
// because we don't know what state it's in.
1933-
self.keepalive.* = false;
1932+
self.keepalive = false;
19341933
} else {
19351934
result.unprocessed = unprocessed;
19361935
}
@@ -1945,7 +1944,7 @@ const Reader = struct {
19451944

19461945
if (response.get("connection")) |connection| {
19471946
if (std.ascii.eqlIgnoreCase(connection, "close")) {
1948-
self.keepalive.* = false;
1947+
self.keepalive = false;
19491948
}
19501949
}
19511950

@@ -2005,7 +2004,7 @@ const Reader = struct {
20052004
}
20062005
const protocol = data[0..9];
20072006
if (std.mem.eql(u8, protocol, "HTTP/1.1 ")) {
2008-
self.keepalive.* = true;
2007+
self.keepalive = true;
20092008
} else if (std.mem.eql(u8, protocol, "HTTP/1.0 ") == false) {
20102009
return error.InvalidStatusLine;
20112010
}
@@ -2387,7 +2386,7 @@ pub const Response = struct {
23872386
return data;
23882387
}
23892388
if (self._done) {
2390-
self._request.requestCompleted(self.header);
2389+
self._request.requestCompleted(self.header, self._reader.keepalive);
23912390
return null;
23922391
}
23932392

@@ -3396,8 +3395,7 @@ const CaptureHandler = struct {
33963395

33973396
fn testReader(state: *State, res: *TestResponse, data: []const u8) !void {
33983397
var status: u16 = 0;
3399-
var keepalive = false;
3400-
var r = Reader.init(state, &keepalive);
3398+
var r = Reader.init(state);
34013399

34023400
// dupe it so that we have a mutable copy
34033401
const owned = try testing.allocator.dupe(u8, data);

0 commit comments

Comments
 (0)