-
Notifications
You must be signed in to change notification settings - Fork 32
/
Network+URLSessionResource.swift
108 lines (86 loc) · 3.25 KB
/
Network+URLSessionResource.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
import Foundation
#if canImport(AlicerceCore)
import AlicerceCore
#endif
extension Network {
public struct URLSessionResource {
public let baseRequestMaking: BaseRequestMaking<URLRequest>
public let errorDecoding: ErrorDecoding<Data, URLResponse>
public let interceptors: [URLSessionResourceInterceptor]
public internal(set) var retryState: Retry.State
public let retryActionPriority: Retry.Action.CompareClosure
public init(
baseRequestMaking: BaseRequestMaking<URLRequest>,
errorDecoding: ErrorDecoding<Data, URLResponse> = .dummy,
interceptors: [URLSessionResourceInterceptor] = [],
retryActionPriority: @escaping Retry.Action.CompareClosure = Retry.Action.mostPrioritary
) {
self.baseRequestMaking = baseRequestMaking
self.errorDecoding = errorDecoding
self.interceptors = interceptors
self.retryState = .empty
self.retryActionPriority = retryActionPriority
}
}
}
extension Network.URLSessionResource {
typealias RequestHandler = (Result<URLRequest, Error>) -> Cancelable
func makeRequest(handler: @escaping RequestHandler) -> Cancelable {
baseRequestMaking.make { [interceptors] requestResult in
var iterator = interceptors.makeIterator()
guard let first = iterator.next() else { return handler(requestResult) }
// chain interceptors recursively
func makeHandler() -> RequestHandler {
return { newResult -> Cancelable in
if let next = iterator.next() {
return next.interceptMakeRequestResult(newResult, handler: makeHandler())
}
return handler(newResult)
}
}
return first.interceptMakeRequestResult(requestResult, handler: makeHandler())
}
}
func interceptScheduledTask(withIdentifier taskIdentifier: Int, request: URLRequest) {
interceptors.forEach {
$0.interceptScheduledTask(withIdentifier: taskIdentifier, request: request, retryState: retryState)
}
}
func interceptSuccessfulTask(
withIdentifier taskIdentifier: Int,
request: URLRequest,
data: Data,
response: URLResponse
) {
interceptors.forEach {
$0.interceptSuccessfulTask(
withIdentifier: taskIdentifier,
request: request,
data: data,
response: response,
retryState: retryState
)
}
}
func interceptFailedTask(
withIdentifier taskIdentifier: Int,
request: URLRequest,
data: Data?,
response: URLResponse?,
error: Network.URLSessionError
) -> Retry.Action {
interceptors
.lazy
.map {
$0.interceptFailedTask(
withIdentifier: taskIdentifier,
request: request,
data: data,
response: response,
error: error,
retryState: self.retryState
)
}
.reduce(Retry.Action.none, retryActionPriority)
}
}