Skip to content

Commit aa66da8

Browse files
authored
Fix request head continuation misuse (#666)
* Fix request head continuation misuse Fixes #664 * remove unused function * format & generate linux tests
1 parent f65f45b commit aa66da8

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

Sources/AsyncHTTPClient/AsyncAwait/Transaction+StateMachine.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,9 @@ extension Transaction {
207207
self.state = .executing(context, .requestHeadSent, .waitingForResponseHead)
208208
return .none
209209
case .deadlineExceededWhileQueued(let continuation):
210-
return .cancelAndFail(executor, continuation, with: HTTPClientError.deadlineExceeded)
210+
let error = HTTPClientError.deadlineExceeded
211+
self.state = .finished(error: error, nil)
212+
return .cancelAndFail(executor, continuation, with: error)
211213

212214
case .finished(error: .some, .none):
213215
return .cancel(executor)

Tests/AsyncHTTPClientTests/TransactionTests+XCTest.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extension TransactionTests {
2626
static var allTests: [(String, (TransactionTests) -> () throws -> Void)] {
2727
return [
2828
("testCancelAsyncRequest", testCancelAsyncRequest),
29+
("testDeadlineExceededWhileQueuedAndExecutorImmediatelyCancelsTask", testDeadlineExceededWhileQueuedAndExecutorImmediatelyCancelsTask),
2930
("testResponseStreamingWorks", testResponseStreamingWorks),
3031
("testIgnoringResponseBodyWorks", testIgnoringResponseBodyWorks),
3132
("testWriteBackpressureWorks", testWriteBackpressureWorks),

Tests/AsyncHTTPClientTests/TransactionTests.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,55 @@ final class TransactionTests: XCTestCase {
5959
}
6060
}
6161

62+
func testDeadlineExceededWhileQueuedAndExecutorImmediatelyCancelsTask() {
63+
guard #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) else { return }
64+
XCTAsyncTest {
65+
let embeddedEventLoop = EmbeddedEventLoop()
66+
defer { XCTAssertNoThrow(try embeddedEventLoop.syncShutdownGracefully()) }
67+
68+
var request = HTTPClientRequest(url: "https://localhost/")
69+
request.method = .GET
70+
var maybePreparedRequest: PreparedRequest?
71+
XCTAssertNoThrow(maybePreparedRequest = try PreparedRequest(request))
72+
guard let preparedRequest = maybePreparedRequest else {
73+
return XCTFail("Expected to have a request here.")
74+
}
75+
let (transaction, responseTask) = await Transaction.makeWithResultTask(
76+
request: preparedRequest,
77+
preferredEventLoop: embeddedEventLoop
78+
)
79+
80+
let queuer = MockTaskQueuer()
81+
transaction.requestWasQueued(queuer)
82+
83+
transaction.deadlineExceeded()
84+
85+
struct Executor: HTTPRequestExecutor {
86+
func writeRequestBodyPart(_: NIOCore.IOData, request: AsyncHTTPClient.HTTPExecutableRequest, promise: NIOCore.EventLoopPromise<Void>?) {
87+
XCTFail()
88+
}
89+
90+
func finishRequestBodyStream(_ task: AsyncHTTPClient.HTTPExecutableRequest, promise: NIOCore.EventLoopPromise<Void>?) {
91+
XCTFail()
92+
}
93+
94+
func demandResponseBodyStream(_: AsyncHTTPClient.HTTPExecutableRequest) {
95+
XCTFail()
96+
}
97+
98+
func cancelRequest(_ task: AsyncHTTPClient.HTTPExecutableRequest) {
99+
task.fail(HTTPClientError.cancelled)
100+
}
101+
}
102+
103+
transaction.willExecuteRequest(Executor())
104+
105+
await XCTAssertThrowsError(try await responseTask.value) { error in
106+
XCTAssertEqualTypeAndValue(error, HTTPClientError.deadlineExceeded)
107+
}
108+
}
109+
}
110+
62111
func testResponseStreamingWorks() {
63112
guard #available(macOS 10.15, iOS 13.0, watchOS 6.0, tvOS 13.0, *) else { return }
64113
XCTAsyncTest {

0 commit comments

Comments
 (0)