mirror of
https://github.com/swift-server/async-http-client.git
synced 2026-06-02 07:37:34 +00:00
Motivation: Users of the HTTPClientResponseDelegate expect that the event loop futures returned from didReceiveHead and didReceiveBodyPart can be used to exert backpressure. To be fair to them, they somewhat can. However, the TaskHandler has a bit of a misunderstanding about how NIO backpressure works, and does not correctly manage the buffer of inbound data. The result of this misunderstanding is that multiple calls to didReceiveBodyPart and didReceiveHead can be outstanding at once. This would likely lead to severe bugs in most delegates, as they do not expect it. We should make things work the way delegate implementers believe it works. Modifications: - Added a buffer to the TaskHandler to avoid delivering data that the delegate is not ready for. - Added a new "pending close" state that keeps track of a state where the TaskHandler has received .end but not yet delivered it to the delegate. This allows better error management. - Added some more tests. - Documented our backpressure commitments. Result: Better respect for backpressure. Resolves #348
139 lines
9.4 KiB
Swift
139 lines
9.4 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the AsyncHTTPClient open source project
|
|
//
|
|
// Copyright (c) 2018-2019 Apple Inc. and the AsyncHTTPClient project authors
|
|
// Licensed under Apache License v2.0
|
|
//
|
|
// See LICENSE.txt for license information
|
|
// See CONTRIBUTORS.txt for the list of AsyncHTTPClient project authors
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// HTTPClientTests+XCTest.swift
|
|
//
|
|
import XCTest
|
|
|
|
///
|
|
/// NOTE: This file was generated by generate_linux_tests.rb
|
|
///
|
|
/// Do NOT edit this file directly as it will be regenerated automatically when needed.
|
|
///
|
|
|
|
extension HTTPClientTests {
|
|
static var allTests: [(String, (HTTPClientTests) -> () throws -> Void)] {
|
|
return [
|
|
("testRequestURI", testRequestURI),
|
|
("testBadRequestURI", testBadRequestURI),
|
|
("testSchemaCasing", testSchemaCasing),
|
|
("testURLSocketPathInitializers", testURLSocketPathInitializers),
|
|
("testConvenienceExecuteMethods", testConvenienceExecuteMethods),
|
|
("testConvenienceExecuteMethodsOverSocket", testConvenienceExecuteMethodsOverSocket),
|
|
("testConvenienceExecuteMethodsOverSecureSocket", testConvenienceExecuteMethodsOverSecureSocket),
|
|
("testGet", testGet),
|
|
("testGetWithDifferentEventLoopBackpressure", testGetWithDifferentEventLoopBackpressure),
|
|
("testPost", testPost),
|
|
("testGetHttps", testGetHttps),
|
|
("testGetHttpsWithIP", testGetHttpsWithIP),
|
|
("testPostHttps", testPostHttps),
|
|
("testHttpRedirect", testHttpRedirect),
|
|
("testHttpHostRedirect", testHttpHostRedirect),
|
|
("testPercentEncoded", testPercentEncoded),
|
|
("testPercentEncodedBackslash", testPercentEncodedBackslash),
|
|
("testMultipleContentLengthHeaders", testMultipleContentLengthHeaders),
|
|
("testStreaming", testStreaming),
|
|
("testFileDownload", testFileDownload),
|
|
("testFileDownloadError", testFileDownloadError),
|
|
("testRemoteClose", testRemoteClose),
|
|
("testReadTimeout", testReadTimeout),
|
|
("testConnectTimeout", testConnectTimeout),
|
|
("testDeadline", testDeadline),
|
|
("testCancel", testCancel),
|
|
("testStressCancel", testStressCancel),
|
|
("testHTTPClientAuthorization", testHTTPClientAuthorization),
|
|
("testProxyPlaintext", testProxyPlaintext),
|
|
("testProxyTLS", testProxyTLS),
|
|
("testProxyPlaintextWithCorrectlyAuthorization", testProxyPlaintextWithCorrectlyAuthorization),
|
|
("testProxyPlaintextWithIncorrectlyAuthorization", testProxyPlaintextWithIncorrectlyAuthorization),
|
|
("testUploadStreaming", testUploadStreaming),
|
|
("testNoContentLengthForSSLUncleanShutdown", testNoContentLengthForSSLUncleanShutdown),
|
|
("testNoContentLengthWithIgnoreErrorForSSLUncleanShutdown", testNoContentLengthWithIgnoreErrorForSSLUncleanShutdown),
|
|
("testCorrectContentLengthForSSLUncleanShutdown", testCorrectContentLengthForSSLUncleanShutdown),
|
|
("testNoContentForSSLUncleanShutdown", testNoContentForSSLUncleanShutdown),
|
|
("testNoResponseForSSLUncleanShutdown", testNoResponseForSSLUncleanShutdown),
|
|
("testNoResponseWithIgnoreErrorForSSLUncleanShutdown", testNoResponseWithIgnoreErrorForSSLUncleanShutdown),
|
|
("testWrongContentLengthForSSLUncleanShutdown", testWrongContentLengthForSSLUncleanShutdown),
|
|
("testWrongContentLengthWithIgnoreErrorForSSLUncleanShutdown", testWrongContentLengthWithIgnoreErrorForSSLUncleanShutdown),
|
|
("testEventLoopArgument", testEventLoopArgument),
|
|
("testDecompression", testDecompression),
|
|
("testDecompressionLimit", testDecompressionLimit),
|
|
("testLoopDetectionRedirectLimit", testLoopDetectionRedirectLimit),
|
|
("testCountRedirectLimit", testCountRedirectLimit),
|
|
("testMultipleConcurrentRequests", testMultipleConcurrentRequests),
|
|
("testWorksWith500Error", testWorksWith500Error),
|
|
("testWorksWithHTTP10Response", testWorksWithHTTP10Response),
|
|
("testWorksWhenServerClosesConnectionAfterReceivingRequest", testWorksWhenServerClosesConnectionAfterReceivingRequest),
|
|
("testSubsequentRequestsWorkWithServerSendingConnectionClose", testSubsequentRequestsWorkWithServerSendingConnectionClose),
|
|
("testSubsequentRequestsWorkWithServerAlternatingBetweenKeepAliveAndClose", testSubsequentRequestsWorkWithServerAlternatingBetweenKeepAliveAndClose),
|
|
("testStressGetHttps", testStressGetHttps),
|
|
("testStressGetHttpsSSLError", testStressGetHttpsSSLError),
|
|
("testFailingConnectionIsReleased", testFailingConnectionIsReleased),
|
|
("testResponseDelayGet", testResponseDelayGet),
|
|
("testIdleTimeoutNoReuse", testIdleTimeoutNoReuse),
|
|
("testStressGetClose", testStressGetClose),
|
|
("testManyConcurrentRequestsWork", testManyConcurrentRequestsWork),
|
|
("testRepeatedRequestsWorkWhenServerAlwaysCloses", testRepeatedRequestsWorkWhenServerAlwaysCloses),
|
|
("testShutdownBeforeTasksCompletion", testShutdownBeforeTasksCompletion),
|
|
("testUncleanShutdownActuallyShutsDown", testUncleanShutdownActuallyShutsDown),
|
|
("testUncleanShutdownCancelsTasks", testUncleanShutdownCancelsTasks),
|
|
("testDoubleShutdown", testDoubleShutdown),
|
|
("testTaskFailsWhenClientIsShutdown", testTaskFailsWhenClientIsShutdown),
|
|
("testRaceNewRequestsVsShutdown", testRaceNewRequestsVsShutdown),
|
|
("testVaryingLoopPreference", testVaryingLoopPreference),
|
|
("testMakeSecondRequestDuringCancelledCallout", testMakeSecondRequestDuringCancelledCallout),
|
|
("testMakeSecondRequestDuringSuccessCallout", testMakeSecondRequestDuringSuccessCallout),
|
|
("testMakeSecondRequestWhilstFirstIsOngoing", testMakeSecondRequestWhilstFirstIsOngoing),
|
|
("testUDSBasic", testUDSBasic),
|
|
("testUDSSocketAndPath", testUDSSocketAndPath),
|
|
("testHTTPPlusUNIX", testHTTPPlusUNIX),
|
|
("testHTTPSPlusUNIX", testHTTPSPlusUNIX),
|
|
("testUseExistingConnectionOnDifferentEL", testUseExistingConnectionOnDifferentEL),
|
|
("testWeRecoverFromServerThatClosesTheConnectionOnUs", testWeRecoverFromServerThatClosesTheConnectionOnUs),
|
|
("testPoolClosesIdleConnections", testPoolClosesIdleConnections),
|
|
("testRacePoolIdleConnectionsAndGet", testRacePoolIdleConnectionsAndGet),
|
|
("testAvoidLeakingTLSHandshakeCompletionPromise", testAvoidLeakingTLSHandshakeCompletionPromise),
|
|
("testAsyncShutdown", testAsyncShutdown),
|
|
("testAsyncShutdownDefaultQueue", testAsyncShutdownDefaultQueue),
|
|
("testValidationErrorsAreSurfaced", testValidationErrorsAreSurfaced),
|
|
("testUploadsReallyStream", testUploadsReallyStream),
|
|
("testUploadStreamingCallinToleratedFromOtsideEL", testUploadStreamingCallinToleratedFromOtsideEL),
|
|
("testWeHandleUsSendingACloseHeaderCorrectly", testWeHandleUsSendingACloseHeaderCorrectly),
|
|
("testWeHandleUsReceivingACloseHeaderCorrectly", testWeHandleUsReceivingACloseHeaderCorrectly),
|
|
("testWeHandleUsSendingACloseHeaderAmongstOtherConnectionHeadersCorrectly", testWeHandleUsSendingACloseHeaderAmongstOtherConnectionHeadersCorrectly),
|
|
("testWeHandleUsReceivingACloseHeaderAmongstOtherConnectionHeadersCorrectly", testWeHandleUsReceivingACloseHeaderAmongstOtherConnectionHeadersCorrectly),
|
|
("testLoggingCorrectlyAttachesRequestInformation", testLoggingCorrectlyAttachesRequestInformation),
|
|
("testNothingIsLoggedAtInfoOrHigher", testNothingIsLoggedAtInfoOrHigher),
|
|
("testAllMethodsLog", testAllMethodsLog),
|
|
("testClosingIdleConnectionsInPoolLogsInTheBackground", testClosingIdleConnectionsInPoolLogsInTheBackground),
|
|
("testUploadStreamingNoLength", testUploadStreamingNoLength),
|
|
("testConnectErrorPropagatedToDelegate", testConnectErrorPropagatedToDelegate),
|
|
("testDelegateCallinsTolerateRandomEL", testDelegateCallinsTolerateRandomEL),
|
|
("testContentLengthTooLongFails", testContentLengthTooLongFails),
|
|
("testContentLengthTooShortFails", testContentLengthTooShortFails),
|
|
("testBodyUploadAfterEndFails", testBodyUploadAfterEndFails),
|
|
("testNoBytesSentOverBodyLimit", testNoBytesSentOverBodyLimit),
|
|
("testDoubleError", testDoubleError),
|
|
("testSSLHandshakeErrorPropagation", testSSLHandshakeErrorPropagation),
|
|
("testSSLHandshakeErrorPropagationDelayedClose", testSSLHandshakeErrorPropagationDelayedClose),
|
|
("testWeCloseConnectionsWhenConnectionCloseSetByServer", testWeCloseConnectionsWhenConnectionCloseSetByServer),
|
|
("testBiDirectionalStreaming", testBiDirectionalStreaming),
|
|
("testSynchronousHandshakeErrorReporting", testSynchronousHandshakeErrorReporting),
|
|
("testFileDownloadChunked", testFileDownloadChunked),
|
|
("testCloseWhileBackpressureIsExertedIsFine", testCloseWhileBackpressureIsExertedIsFine),
|
|
("testErrorAfterCloseWhileBackpressureExerted", testErrorAfterCloseWhileBackpressureExerted),
|
|
]
|
|
}
|
|
}
|