-
Notifications
You must be signed in to change notification settings - Fork 32
/
URLSessionResourceInterceptor.swift
156 lines (131 loc) · 5.51 KB
/
URLSessionResourceInterceptor.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import Foundation
#if canImport(AlicerceCore)
import AlicerceCore
#endif
/// A type representing a resource interceptor.
public protocol URLSessionResourceInterceptor {
/// An interceptor's intercept request handler closure, invoked when the make request interception finishes.
typealias InterceptRequestHandler = (Result<URLRequest, Error>) -> Cancelable
/// Intercepts a request being made before being scheduled, either the base request from the
/// `URLSessionResource.baseRequestMaking.make` closure (initial), or from the previous interceptor's
/// `interceptMakeRequestResult` (subsequent).
///
/// - Parameters:
/// - result: The current request result, either the base or already intercepted by previous chain elements.
/// - handler: The closure to invoke with the intercepted request result (modified or not).
@discardableResult
func interceptMakeRequestResult(
_ result: Result<URLRequest, Error>,
handler: @escaping InterceptRequestHandler
) -> Cancelable
/// Intercepts a `URLSessionDataTask` scheduled by the `URLSessionNetworkStack` for a particular `Resource`'s
/// request.
///
/// - Parameters:
/// - identifier: The task's identifier, obtained from `URLSessionTask.taskIdentifier`.
/// - request: The current request being scheduled for this resource.
/// - retryState: The current retry state of the resource.
func interceptScheduledTask(withIdentifier identifier: Int, request: URLRequest, retryState: Retry.State)
/// Intercepts a successful `URLSessionDataTask` for a particular `Resource`'s request.
///
/// - Parameters:
/// - identifier: The task's identifier, obtained from `URLSessionTask.taskIdentifier`.
/// - request: The current request being scheduled for this resource.
/// - data: The network payload returned by the session task.
/// - response: The response returned by the session task.
/// - retryState: The current retry state of the resource.
func interceptSuccessfulTask(
withIdentifier identifier: Int,
request: URLRequest,
data: Data,
response: URLResponse,
retryState: Retry.State
)
/// Intercepts a failed `URLSessionDataTask` for a particular `Resource`'s request.
///
/// - Parameters:
/// - identifier: The task's identifier, obtained from `URLSessionTask.taskIdentifier`.
/// - request: The current request being scheduled for this resource.
/// - data: The network payload returned by the session task.
/// - response: The response returned by the session task.
/// - error: The error which caused the oepration to fail.
/// - retryState: The current retry state of the resource.
///
/// - Returns: The retry action to apply to the operation.
func interceptFailedTask( // swiftlint:disable:this function_parameter_count
withIdentifier identifier: Int,
request: URLRequest,
data: Data?,
response: URLResponse?,
error: Network.URLSessionError,
retryState: Retry.State
) -> Retry.Action
}
// MARK: - Default implementation
extension URLSessionResourceInterceptor {
@discardableResult
public func interceptMakeRequestResult(
_ result: Result<URLRequest, Error>,
handler: @escaping InterceptRequestHandler
) -> Cancelable {
return handler(result)
}
public func interceptScheduledTask(withIdentifier identifier: Int, request: URLRequest, retryState: Retry.State) {}
public func interceptSuccessfulTask(
withIdentifier identifier: Int,
request: URLRequest,
data: Data,
response: URLResponse,
retryState: Retry.State
) {}
// swiftlint:disable:next function_parameter_count
public func interceptFailedTask(
withIdentifier identifier: Int,
request: URLRequest,
data: Data?,
response: URLResponse?,
error: Network.URLSessionError,
retryState: Retry.State
) -> Retry.Action {
.none
}
}
// MARK: - URLRequestAuthenticator default implementation
extension URLSessionResourceInterceptor where Self: URLRequestAuthenticator {
public func interceptMakeRequestResult(
_ result: Result<URLRequest, Error>,
handler: @escaping InterceptRequestHandler
) -> Cancelable {
switch result {
case .success(let newRequest):
return authenticateRequest(newRequest) { handler($0.mapError { $0 as Error }) }
case .failure(let error):
return handler(.failure(error))
}
}
// swiftlint:disable:next function_parameter_count
public func interceptFailedTask(
withIdentifier identifier: Int,
request: URLRequest,
data: Data?,
response: URLResponse?,
error: Network.URLSessionError,
retryState: Retry.State
) -> Retry.Action {
evaluateFailedRequest(request, data: data, response: response, error: error, retryState: retryState)
}
}
// MARK: - Network.URLSessionRetryPolicy default implementation
extension Network.URLSessionRetryPolicy: URLSessionResourceInterceptor {
// swiftlint:disable:next function_parameter_count
public func interceptFailedTask(
withIdentifier identifier: Int,
request: URLRequest,
data: Data?,
response: URLResponse?,
error: Network.URLSessionError,
retryState: Retry.State
) -> Retry.Action {
shouldRetry(with: error, state: retryState, metadata: (request, data, response))
}
}