Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Sources/AsyncHTTPClient/HTTPClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -795,7 +795,8 @@ public class HTTPClient {

self.poolManager.executeRequest(requestBag)
} catch {
task.fail(with: error, delegateType: Delegate.self)
delegate.didReceiveError(task: task, error)
task.failInternal(with: error)
}

return task
Expand Down
6 changes: 3 additions & 3 deletions Sources/AsyncHTTPClient/HTTPHandler.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1024,9 +1024,9 @@ extension HTTPClient {
taskDelegate?.fail(error)
}

func fail<Delegate: HTTPClientResponseDelegate>(
with error: Error,
delegateType: Delegate.Type
/// Called internally only, used to fail a task from within the state machine functionality.
func failInternal(
with error: Error
) {
self.promise.fail(error)
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/AsyncHTTPClient/RequestBag.swift
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ final class RequestBag<Delegate: HTTPClientResponseDelegate & Sendable>: Sendabl
executor.cancelRequest(self)
case .failTaskAndCancelExecutor(let error, let executor):
self.delegate.didReceiveError(task: self.task, error)
self.task.fail(with: error, delegateType: Delegate.self)
self.task.failInternal(with: error)
executor.cancelRequest(self)
case .none:
break
Expand Down Expand Up @@ -181,7 +181,7 @@ final class RequestBag<Delegate: HTTPClientResponseDelegate & Sendable>: Sendabl
switch action {
case .failTask(let error):
self.delegate.didReceiveError(task: self.task, error)
self.task.fail(with: error, delegateType: Delegate.self)
self.task.failInternal(with: error)
return self.task.eventLoop.makeFailedFuture(error)

case .failFuture(let error):
Expand Down
31 changes: 31 additions & 0 deletions Tests/AsyncHTTPClientTests/HTTPClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3357,6 +3357,37 @@ final class HTTPClientTests: XCTestCaseHTTPClientTestsBaseClass {
XCTAssertNoThrow(try future.wait())
}

func testDelegateGetsErrorsFromCreatingRequestBag() throws {
// We want to test that we propagate errors to the delegate from failures to construct the
// request bag. Those errors only come from invalid headers.
final class TestDelegate: HTTPClientResponseDelegate, Sendable {
typealias Response = Void
let error: NIOLockedValueBox<Error?> = .init(nil)
func didFinishRequest(task: HTTPClient.Task<Void>) throws {}
func didReceiveError(task: HTTPClient.Task<Response>, _ error: Error) {
self.error.withLockedValue { $0 = error }
}
}

let httpClient = HTTPClient(
eventLoopGroupProvider: .shared(self.clientGroup)
)

defer {
XCTAssertNoThrow(try httpClient.syncShutdown())
}

// 198.51.100.254 is reserved for documentation only
var request = try HTTPClient.Request(url: "http://198.51.100.254:65535/get")
request.headers.replaceOrAdd(name: "Not-ASCII", value: "not-fine\n")
let delegate = TestDelegate()

XCTAssertThrowsError(try httpClient.execute(request: request, delegate: delegate).wait()) {
XCTAssertEqualTypeAndValue($0, HTTPClientError.invalidHeaderFieldValues(["not-fine\n"]))
XCTAssertEqualTypeAndValue(delegate.error.withLockedValue { $0 }, HTTPClientError.invalidHeaderFieldValues(["not-fine\n"]))
}
}

func testContentLengthTooLongFails() throws {
let url = self.defaultHTTPBinURLPrefix + "post"
XCTAssertThrowsError(
Expand Down
Loading