Skip to content

Commit 04ac8da

Browse files
committed
Fix existing behaviour
1 parent be7759e commit 04ac8da

File tree

5 files changed

+13
-28
lines changed

5 files changed

+13
-28
lines changed

Diff for: Sources/AsyncHTTPClient/ConnectionPool/HTTPRequestStateMachine.swift

+1-7
Original file line numberDiff line numberDiff line change
@@ -529,13 +529,7 @@ struct HTTPRequestStateMachine {
529529
preconditionFailure("How can we receive a response head before sending a request head ourselves. Invalid state: \(self.state)")
530530

531531
case .running(_, .waitingForHead):
532-
// If we receive a http response header with a status code of 1xx, we ignore the header
533-
// except for 101, which we consume.
534-
// If the remote closes the connection after sending a 1xx (not 101) response head, we
535-
// will receive a response end from the parser. We need to protect against this case.
536-
let error = HTTPClientError.httpEndReceivedAfterHeadWith1xx
537-
self.state = .failed(error)
538-
return .failRequest(error, .close)
532+
preconditionFailure("How can we receive a response end, if we haven't a received a head. Invalid state: \(self.state)")
539533

540534
case .running(.streaming(let expectedBodyLength, let sentBodyBytes, let producerState), .receivingBody(let head, var responseStreamState))
541535
where head.status.code < 300:

Diff for: Sources/AsyncHTTPClient/HTTPClient.swift

+1
Original file line numberDiff line numberDiff line change
@@ -996,5 +996,6 @@ public struct HTTPClientError: Error, Equatable, CustomStringConvertible {
996996
/// - Tasks are not processed fast enough on the existing connections, to process all waiters in time
997997
public static let getConnectionFromPoolTimeout = HTTPClientError(code: .getConnectionFromPoolTimeout)
998998

999+
@available(*, deprecated, message: "AsyncHTTPClient now correctly supports informational headers. For this reason `httpEndReceivedAfterHeadWith1xx` will not be thrown anymore.")
9991000
public static let httpEndReceivedAfterHeadWith1xx = HTTPClientError(code: .httpEndReceivedAfterHeadWith1xx)
10001001
}

Diff for: Tests/AsyncHTTPClientTests/HTTP1ConnectionStateMachineTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ class HTTP1ConnectionStateMachineTests: XCTestCase {
265265
XCTAssertEqual(newRequestAction, .sendRequestHead(requestHead, startBody: false))
266266
let responseHead = HTTPResponseHead(version: .http1_1, status: .init(statusCode: 103, reasonPhrase: "Early Hints"))
267267
XCTAssertEqual(state.channelRead(.head(responseHead)), .wait)
268-
XCTAssertEqual(state.channelRead(.end(nil)), .failRequest(HTTPClientError.httpEndReceivedAfterHeadWith1xx, .close))
268+
XCTAssertEqual(state.channelInactive(), .failRequest(HTTPClientError.remoteConnectionClosed, .none))
269269
}
270270
}
271271

Diff for: Tests/AsyncHTTPClientTests/HTTP1ConnectionTests+XCTest.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ extension HTTP1ConnectionTests {
3333
("testConnectionClosesOnRandomlyAppearingCloseHeader", testConnectionClosesOnRandomlyAppearingCloseHeader),
3434
("testConnectionClosesAfterTheRequestWithoutHavingSentAnCloseHeader", testConnectionClosesAfterTheRequestWithoutHavingSentAnCloseHeader),
3535
("testConnectionIsClosedAfterSwitchingProtocols", testConnectionIsClosedAfterSwitchingProtocols),
36-
("testConnectionDoesntCrashAfterConnectionCloseAndEarlyHints", testConnectionDoesntCrashAfterConnectionCloseAndEarlyHints),
36+
("testConnectionDropAfterEarlyHints", testConnectionDropAfterEarlyHints),
3737
("testConnectionIsClosedIfResponseIsReceivedBeforeRequest", testConnectionIsClosedIfResponseIsReceivedBeforeRequest),
3838
("testDoubleHTTPResponseLine", testDoubleHTTPResponseLine),
3939
("testDownloadStreamingBackpressure", testDownloadStreamingBackpressure),

Diff for: Tests/AsyncHTTPClientTests/HTTP1ConnectionTests.swift

+9-19
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ class HTTP1ConnectionTests: XCTestCase {
430430
XCTAssertEqual(response?.body, nil)
431431
}
432432

433-
func testConnectionDoesntCrashAfterConnectionCloseAndEarlyHints() {
433+
func testConnectionDropAfterEarlyHints() {
434434
let embedded = EmbeddedChannel()
435435
let logger = Logger(label: "test.http1.connection")
436436

@@ -481,25 +481,15 @@ class HTTP1ConnectionTests: XCTestCase {
481481
XCTAssertEqual(connectionDelegate.hitConnectionReleased, 0)
482482
XCTAssertNoThrow(try embedded.writeInbound(ByteBuffer(string: responseString)))
483483

484-
if !embedded.isActive {
485-
// behavior before https://github.com/apple/swift-nio/pull/1984
486-
embedded.embeddedEventLoop.run() // tick once to run futures.
487-
XCTAssertEqual(connectionDelegate.hitConnectionClosed, 1)
488-
XCTAssertEqual(connectionDelegate.hitConnectionReleased, 0)
484+
XCTAssertTrue(embedded.isActive, "The connection remains active after the informational response head")
485+
XCTAssertNoThrow(try embedded.close().wait(), "the connection was closed")
489486

490-
XCTAssertThrowsError(try requestBag.task.futureResult.wait()) {
491-
XCTAssertEqual($0 as? HTTPClientError, .httpEndReceivedAfterHeadWith1xx)
492-
}
493-
} else {
494-
// behavior after https://github.com/apple/swift-nio/pull/1984
495-
XCTAssertNoThrow(try embedded.close().wait())
496-
embedded.embeddedEventLoop.run() // tick once to run futures.
497-
XCTAssertEqual(connectionDelegate.hitConnectionClosed, 1)
498-
XCTAssertEqual(connectionDelegate.hitConnectionReleased, 0)
499-
500-
XCTAssertThrowsError(try requestBag.task.futureResult.wait()) {
501-
XCTAssertEqual($0 as? HTTPClientError, .remoteConnectionClosed)
502-
}
487+
embedded.embeddedEventLoop.run() // tick once to run futures.
488+
XCTAssertEqual(connectionDelegate.hitConnectionClosed, 1)
489+
XCTAssertEqual(connectionDelegate.hitConnectionReleased, 0)
490+
491+
XCTAssertThrowsError(try requestBag.task.futureResult.wait()) {
492+
XCTAssertEqual($0 as? HTTPClientError, .remoteConnectionClosed)
503493
}
504494
}
505495

0 commit comments

Comments
 (0)