Skip to content

Commit 589a763

Browse files
committed
🧪 📚 ✨ Adds zip convenience to request plugins.
- Adds convenience functions to HTTPRequest for each plugin's zip. - Adds tests to validate the convenience functions. - Adds some mark docs.
1 parent a57c4f2 commit 589a763

File tree

11 files changed

+124
-3
lines changed

11 files changed

+124
-3
lines changed

Sources/HTTPNetworking/Plugins/Adaptors/Adaptor.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import Foundation
22

3+
// MARK: - AdaptationHandler
4+
35
public typealias AdaptationHandler = (
46
_ request: URLRequest,
57
_ session: URLSession
68
) async throws -> URLRequest
79

10+
// MARK: - Adaptor
11+
812
/// An ``HTTPRequestAdaptor`` that can be used to manipulate a `URLRequest` before it is sent out over the network.
913
public struct Adaptor: HTTPRequestAdaptor {
1014

Sources/HTTPNetworking/Plugins/Adaptors/HeadersAdaptor.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import Foundation
22

3+
// MARK: - HeadersAdaptor
4+
35
/// An ``HTTPRequestAdaptor`` that can be used to append HTTP headers to a request before it is sent out over the network.
46
public struct HeadersAdaptor: HTTPRequestAdaptor {
57

Sources/HTTPNetworking/Plugins/Adaptors/ParametersAdaptor.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import Foundation
22

3+
// MARK: - ParametersAdaptor
4+
35
/// An ``HTTPRequestAdaptor`` that can be used to append query parameters to a request before it is sent out over the network.
46
///
57
/// > Warning: This adaptor will **not** overwrite existing parameters, instead it will append to existing parameters.

Sources/HTTPNetworking/Plugins/Adaptors/ZipAdaptor.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import Foundation
22

3+
// MARK: - ZipAdaptor
4+
35
/// An ``HTTPRequestAdaptor`` that combines multiple adaptors into one, executing each adaptation in sequence.
46
public struct ZipAdaptor: HTTPRequestAdaptor {
57

@@ -37,3 +39,13 @@ public struct ZipAdaptor: HTTPRequestAdaptor {
3739
return request
3840
}
3941
}
42+
43+
// MARK: - HTTPRequest + ZipAdaptor
44+
45+
extension HTTPRequest {
46+
/// Applies a ``ZipAdaptor`` that bundles up all the provided adaptors.
47+
@discardableResult
48+
public func adapt(zipping adaptors: [any HTTPRequestAdaptor]) -> Self {
49+
adapt(with: ZipAdaptor(adaptors))
50+
}
51+
}

Sources/HTTPNetworking/Plugins/HTTPResponseValidator.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import Foundation
22

3+
// MARK: - ValidationResult
4+
35
public typealias ValidationResult = Result<Void, Error>
46

7+
// MARK: - HTTPResponseValidator
8+
59
/// An ``HTTPResponseValidator`` is used to validate the response from an ``HTTPRequest``.
610
///
711
/// By conforming to ``HTTPResponseValidator`` you can implement both simple and complex logic for validating

Sources/HTTPNetworking/Plugins/Retriers/Retrier.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import Foundation
22

3+
// MARK: - RetryHandler
4+
35
public typealias RetryHandler = (
46
_ request: URLRequest,
57
_ session: URLSession,
@@ -8,6 +10,8 @@ public typealias RetryHandler = (
810
_ previousAttempts: Int
911
) async throws -> RetryStrategy
1012

13+
// MARK: - Retrier
14+
1115
/// An ``HTTPRequestRetrier`` that can be used to retry an ``HTTPRequest`` upon failure.
1216
public struct Retrier: HTTPRequestRetrier {
1317

Sources/HTTPNetworking/Plugins/Retriers/ZipRetrier.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import Foundation
22

3+
// MARK: - ZipRetrier
4+
35
/// An ``HTTPRequestRetrier`` that combines multiple retriers into one, executing each retrier in sequence.
46
public struct ZipRetrier: HTTPRequestRetrier {
57

@@ -55,3 +57,13 @@ public struct ZipRetrier: HTTPRequestRetrier {
5557
return .concede
5658
}
5759
}
60+
61+
// MARK: - HTTPRequest + ZipRetrier
62+
63+
extension HTTPRequest {
64+
/// Applies a ``ZipRetrier`` that bundles up all the provided retriers.
65+
@discardableResult
66+
public func retry(zipping retriers: [any HTTPRequestRetrier]) -> Self {
67+
retry(with: ZipRetrier(retriers))
68+
}
69+
}

Sources/HTTPNetworking/Plugins/Validators/ZipValidator.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import Foundation
22

3+
// MARK: - ZipValidator
4+
35
/// An ``HTTPResponseValidator`` that combines multiple validators into one, executing each validation in sequence.
46
public struct ZipValidator: HTTPResponseValidator {
57

@@ -38,3 +40,13 @@ public struct ZipValidator: HTTPResponseValidator {
3840
return .success
3941
}
4042
}
43+
44+
// MARK: - HTTPRequest + ZipValidator
45+
46+
extension HTTPRequest {
47+
/// Applies a ``ZipValidator`` that bundles up all the provided validators.
48+
@discardableResult
49+
public func validate(zipping validators: [any HTTPResponseValidator]) -> Self {
50+
validate(with: ZipValidator(validators))
51+
}
52+
}

Tests/HTTPNetworkingTests/Plugins/Adaptors/ZipAdaptorTests.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,27 @@ class ZipAdaptorTests: XCTestCase {
5151
}
5252
}
5353

54-
await fulfillment(of: [adaptorOneExpectation, adaptorTwoExpectation])
54+
await fulfillment(of: [adaptorOneExpectation, adaptorTwoExpectation], enforceOrder: true)
55+
}
56+
57+
func test_zipAdaptor_adaptorConvenience_isAddedToRequestAdaptors() async throws {
58+
let client = HTTPClient()
59+
let request = client.request(for: .get, to: .mock, expecting: String.self)
60+
let expectationOne = expectation(description: "Expected adaptor one to be called.")
61+
let expectationTwo = expectation(description: "Expected adaptor two to be called.")
62+
request.adapt(zipping: [
63+
Adaptor { request, _ in
64+
expectationOne.fulfill()
65+
return request
66+
},
67+
Adaptor { request, _ in
68+
expectationTwo.fulfill()
69+
return request
70+
},
71+
])
72+
73+
_ = try await request.adaptors.first?.adapt(request.request, for: client.dispatcher.session)
74+
75+
await fulfillment(of: [expectationOne, expectationTwo], enforceOrder: true)
5576
}
5677
}

Tests/HTTPNetworkingTests/Plugins/Retriers/ZipRetrierTests.swift

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,33 @@ class ZipRetrierTests: XCTestCase {
6363
}
6464
}
6565

66-
await fulfillment(of: [retrierOneExpectation, retrierTwoExpectation])
66+
await fulfillment(of: [retrierOneExpectation, retrierTwoExpectation], enforceOrder: true)
67+
}
68+
69+
func test_zipRetrier_retrierConvenience_isAddedToRequestRetriers() async throws {
70+
let client = HTTPClient()
71+
let request = client.request(for: .get, to: .mock, expecting: String.self)
72+
let expectationOne = expectation(description: "Expected retrier one to be called.")
73+
let expectationTwo = expectation(description: "Expected retrier two to be called.")
74+
request.retry(zipping: [
75+
Retrier { _, _, _, _, _ in
76+
expectationOne.fulfill()
77+
return .concede
78+
},
79+
Retrier { _, _, _, _, _ in
80+
expectationTwo.fulfill()
81+
return .concede
82+
},
83+
])
84+
85+
_ = try await request.retriers.first?.retry(
86+
request.request,
87+
for: .shared,
88+
with: nil,
89+
dueTo: URLError(.cannotParseResponse),
90+
previousAttempts: 0
91+
)
92+
93+
await fulfillment(of: [expectationOne, expectationTwo], enforceOrder: true)
6794
}
6895
}

0 commit comments

Comments
 (0)