Skip to content

Commit f64ae5f

Browse files
committed
Fixes a bug
1 parent 96fbbbd commit f64ae5f

File tree

4 files changed

+43
-6
lines changed

4 files changed

+43
-6
lines changed

Sources/AsyncHTTPClient/ConnectionPool/HTTPRequestStateMachine+Demand.swift

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,18 @@ extension HTTPRequestStateMachine {
6161
}
6262
}
6363

64-
mutating func channelReadComplete() -> CircularBuffer<ByteBuffer> {
64+
mutating func channelReadComplete() -> CircularBuffer<ByteBuffer>? {
6565
switch self.state {
6666
case .waitingForBytes(let buffer):
67-
var newBuffer = buffer
68-
newBuffer.removeAll(keepingCapacity: true)
69-
self.state = .waitingForReadOrDemand(newBuffer)
70-
return buffer
67+
if buffer.isEmpty {
68+
self.state = .waitingForRead(buffer)
69+
return nil
70+
} else {
71+
var newBuffer = buffer
72+
newBuffer.removeAll(keepingCapacity: true)
73+
self.state = .waitingForReadOrDemand(newBuffer)
74+
return buffer
75+
}
7176

7277
case .waitingForRead,
7378
.waitingForDemand,

Sources/AsyncHTTPClient/ConnectionPool/HTTPRequestStateMachine.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,11 @@ struct HTTPRequestStateMachine {
426426
return self.avoidingStateMachineCoW { (state) -> Action in
427427
let buffer = streamState.channelReadComplete()
428428
state = .running(requestState, .receivingBody(head, streamState))
429-
return .forwardResponseBodyParts(buffer)
429+
if let buffer = buffer {
430+
return .forwardResponseBodyParts(buffer)
431+
} else {
432+
return .wait
433+
}
430434
}
431435

432436
case .modifying:

Tests/AsyncHTTPClientTests/HTTPRequestStateMachineTests+XCTest.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ extension HTTPRequestStateMachineTests {
3838
("testRequestIsNotSendUntilChannelIsWritable", testRequestIsNotSendUntilChannelIsWritable),
3939
("testConnectionBecomesInactiveWhileWaitingForWritable", testConnectionBecomesInactiveWhileWaitingForWritable),
4040
("testResponseReadingWithBackpressure", testResponseReadingWithBackpressure),
41+
("testChannelReadCompleteTriggersButNoBodyDataWasReceivedSoFar", testChannelReadCompleteTriggersButNoBodyDataWasReceivedSoFar),
4142
("testResponseReadingWithBackpressureEndOfResponseAllowsReadEventsToTriggerDirectly", testResponseReadingWithBackpressureEndOfResponseAllowsReadEventsToTriggerDirectly),
4243
("testCancellingARequestInStateInitializedKeepsTheConnectionAlive", testCancellingARequestInStateInitializedKeepsTheConnectionAlive),
4344
("testCancellingARequestBeforeBeingSendKeepsTheConnectionAlive", testCancellingARequestBeforeBeingSendKeepsTheConnectionAlive),

Tests/AsyncHTTPClientTests/HTTPRequestStateMachineTests.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,33 @@ class HTTPRequestStateMachineTests: XCTestCase {
279279
XCTAssertEqual(state.demandMoreResponseBodyParts(), .wait)
280280
}
281281

282+
func testChannelReadCompleteTriggersButNoBodyDataWasReceivedSoFar() {
283+
var state = HTTPRequestStateMachine(isChannelWritable: true)
284+
let requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: "/")
285+
let metadata = RequestFramingMetadata(connectionClose: false, body: .none)
286+
XCTAssertEqual(state.startRequest(head: requestHead, metadata: metadata), .sendRequestHead(requestHead, startBody: false))
287+
288+
let responseHead = HTTPResponseHead(version: .http1_1, status: .ok, headers: HTTPHeaders([("content-length", "12")]))
289+
XCTAssertEqual(state.channelRead(.head(responseHead)), .forwardResponseHead(responseHead, pauseRequestBodyStream: false))
290+
let part0 = ByteBuffer(bytes: 0...3)
291+
let part1 = ByteBuffer(bytes: 4...7)
292+
let part2 = ByteBuffer(bytes: 8...11)
293+
XCTAssertEqual(state.channelReadComplete(), .wait)
294+
XCTAssertEqual(state.read(), .read)
295+
XCTAssertEqual(state.channelRead(.body(part0)), .wait)
296+
XCTAssertEqual(state.channelRead(.body(part1)), .wait)
297+
XCTAssertEqual(state.channelReadComplete(), .forwardResponseBodyParts(.init([part0, part1])))
298+
XCTAssertEqual(state.read(), .wait)
299+
XCTAssertEqual(state.demandMoreResponseBodyParts(), .read)
300+
XCTAssertEqual(state.channelReadComplete(), .wait)
301+
XCTAssertEqual(state.read(), .read)
302+
XCTAssertEqual(state.channelRead(.body(part2)), .wait)
303+
XCTAssertEqual(state.channelRead(.end(nil)), .succeedRequest(.none, .init([part2])))
304+
XCTAssertEqual(state.channelReadComplete(), .wait)
305+
XCTAssertEqual(state.read(), .read)
306+
XCTAssertEqual(state.demandMoreResponseBodyParts(), .wait)
307+
}
308+
282309
func testResponseReadingWithBackpressureEndOfResponseAllowsReadEventsToTriggerDirectly() {
283310
var state = HTTPRequestStateMachine(isChannelWritable: true)
284311
let requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: "/")

0 commit comments

Comments
 (0)