Skip to content

Commit e097940

Browse files
committed
fix bodyLengthMissmatch error handling
1 parent 6426c00 commit e097940

File tree

3 files changed

+29
-3
lines changed

3 files changed

+29
-3
lines changed

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -198,14 +198,14 @@ struct HTTPRequestStateMachine {
198198
self.state = .failed(error)
199199
return .failRequest(error, .none)
200200

201-
case .running(.streaming, .waitingForHead),
201+
case .running(.streaming, .waitingForHead) where error as? NIOSSLError == .uncleanShutdown,
202202
.running(.endSent, .waitingForHead) where error as? NIOSSLError == .uncleanShutdown:
203203
// if we received a NIOSSL.uncleanShutdown before we got an answer we should handle
204204
// this like a normal connection close. We will receive a call to channelInactive after
205205
// this error.
206206
return .wait
207207

208-
case .running(.streaming, .receivingBody(let responseHead, _)),
208+
case .running(.streaming, .receivingBody(let responseHead, _)) where error as? NIOSSLError == .uncleanShutdown,
209209
.running(.endSent, .receivingBody(let responseHead, _)) where error as? NIOSSLError == .uncleanShutdown:
210210
// This code is only reachable for request and responses, which we expect to have a body.
211211
// We depend on logic from the HTTPResponseDecoder here. The decoder will emit an
@@ -270,7 +270,7 @@ struct HTTPRequestStateMachine {
270270

271271
if let expected = expectedBodyLength, sentBodyBytes + part.readableBytes > expected {
272272
let error = HTTPClientError.bodyLengthMismatch
273-
273+
self.state = .failed(error)
274274
return .failRequest(error, .close)
275275
}
276276

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

+2
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ extension HTTPRequestStateMachineTests {
5454
("testCanReadHTTP1_0ResponseWithBody", testCanReadHTTP1_0ResponseWithBody),
5555
("testFailHTTP1_0RequestThatIsStillUploading", testFailHTTP1_0RequestThatIsStillUploading),
5656
("testFailHTTP1RequestWithoutContentLengthWithNIOSSLErrorUncleanShutdown", testFailHTTP1RequestWithoutContentLengthWithNIOSSLErrorUncleanShutdown),
57+
("testNIOSSLErrorUncleanShutdownShouldBeTreatedAsRemoteConnectionCloseWhileInWaitingForHeadState", testNIOSSLErrorUncleanShutdownShouldBeTreatedAsRemoteConnectionCloseWhileInWaitingForHeadState),
58+
("testArbitraryErrorShouldBeTreatedAsARequestFailureWhileInWaitingForHeadState", testArbitraryErrorShouldBeTreatedAsARequestFailureWhileInWaitingForHeadState),
5759
("testFailHTTP1RequestWithContentLengthWithNIOSSLErrorUncleanShutdownButIgnoreIt", testFailHTTP1RequestWithContentLengthWithNIOSSLErrorUncleanShutdownButIgnoreIt),
5860
("testFailHTTPRequestWithContentLengthBecauseOfChannelInactiveWaitingForDemand", testFailHTTPRequestWithContentLengthBecauseOfChannelInactiveWaitingForDemand),
5961
("testFailHTTPRequestWithContentLengthBecauseOfChannelInactiveWaitingForRead", testFailHTTPRequestWithContentLengthBecauseOfChannelInactiveWaitingForRead),

Diff for: Tests/AsyncHTTPClientTests/HTTPRequestStateMachineTests.swift

+24
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ class HTTPRequestStateMachineTests: XCTestCase {
8282
}
8383

8484
XCTAssertEqual(error as? HTTPClientError, .bodyLengthMismatch)
85+
86+
// if another error happens the new one is ignored
87+
XCTAssertEqual(state.errorHappened(HTTPClientError.remoteConnectionClosed), .wait)
8588
}
8689

8790
func testPOSTContentLengthIsTooShort() {
@@ -522,6 +525,27 @@ class HTTPRequestStateMachineTests: XCTestCase {
522525
XCTAssertEqual(state.channelInactive(), .wait)
523526
}
524527

528+
func testNIOSSLErrorUncleanShutdownShouldBeTreatedAsRemoteConnectionCloseWhileInWaitingForHeadState() {
529+
var state = HTTPRequestStateMachine(isChannelWritable: true)
530+
let requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: "/")
531+
let metadata = RequestFramingMetadata(connectionClose: false, body: .fixedSize(0))
532+
XCTAssertEqual(state.startRequest(head: requestHead, metadata: metadata), .sendRequestHead(requestHead, startBody: false))
533+
534+
XCTAssertEqual(state.errorHappened(NIOSSLError.uncleanShutdown), .wait)
535+
XCTAssertEqual(state.channelInactive(), .failRequest(HTTPClientError.remoteConnectionClosed, .none))
536+
}
537+
538+
func testArbitraryErrorShouldBeTreatedAsARequestFailureWhileInWaitingForHeadState() {
539+
struct ArbitraryError: Error {}
540+
var state = HTTPRequestStateMachine(isChannelWritable: true)
541+
let requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: "/")
542+
let metadata = RequestFramingMetadata(connectionClose: false, body: .fixedSize(0))
543+
XCTAssertEqual(state.startRequest(head: requestHead, metadata: metadata), .sendRequestHead(requestHead, startBody: false))
544+
545+
XCTAssertEqual(state.errorHappened(ArbitraryError()), .failRequest(ArbitraryError(), .close))
546+
XCTAssertEqual(state.channelInactive(), .wait)
547+
}
548+
525549
func testFailHTTP1RequestWithContentLengthWithNIOSSLErrorUncleanShutdownButIgnoreIt() {
526550
var state = HTTPRequestStateMachine(isChannelWritable: true)
527551
let requestHead = HTTPRequestHead(version: .http1_1, method: .GET, uri: "/")

0 commit comments

Comments
 (0)