forked from apollographql/apollo-ios
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathNetworkFetchInterceptor.swift
More file actions
93 lines (79 loc) · 2.25 KB
/
NetworkFetchInterceptor.swift
File metadata and controls
93 lines (79 loc) · 2.25 KB
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
import Foundation
#if !COCOAPODS
import ApolloAPI
#endif
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
/// An interceptor which actually fetches data from the network.
public class NetworkFetchInterceptor: ApolloInterceptor, Cancellable {
let client: URLSessionClient
@Atomic private var currentTask: URLSessionTask?
public var id: String = UUID().uuidString
/// Designated initializer.
///
/// - Parameter client: The `URLSessionClient` to use to fetch data
public init(client: URLSessionClient) {
self.client = client
}
public func interceptAsync<Operation: GraphQLOperation>(
chain: any RequestChain,
request: HTTPRequest<Operation>,
response: HTTPResponse<Operation>?,
completion: @escaping (Result<GraphQLResult<Operation.Data>, any Error>) -> Void) {
let urlRequest: URLRequest
do {
urlRequest = try request.toURLRequest()
} catch {
chain.handleErrorAsync(
error,
request: request,
response: response,
completion: completion
)
return
}
let taskDescription = "\(Operation.operationType) \(Operation.operationName)"
let task = self.client.sendRequest(urlRequest, taskDescription: taskDescription) { [weak self] result in
guard let self = self else {
return
}
defer {
if Operation.operationType != .subscription {
self.$currentTask.mutate { $0 = nil }
}
}
guard !chain.isCancelled else {
return
}
switch result {
case .failure(let error):
chain.handleErrorAsync(
error,
request: request,
response: response,
completion: completion
)
case .success(let (data, httpResponse)):
let response = HTTPResponse<Operation>(
response: httpResponse,
rawData: data,
parsedResponse: nil
)
chain.proceedAsync(
request: request,
response: response,
interceptor: self,
completion: completion
)
}
}
self.$currentTask.mutate { $0 = task }
}
public func cancel() {
guard let task = self.currentTask else {
return
}
task.cancel()
}
}