-
Notifications
You must be signed in to change notification settings - Fork 749
Expand file tree
/
Copy pathAutomaticPersistedQueryInterceptor.swift
More file actions
111 lines (94 loc) · 3.53 KB
/
AutomaticPersistedQueryInterceptor.swift
File metadata and controls
111 lines (94 loc) · 3.53 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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import Foundation
#if !COCOAPODS
import ApolloMigrationAPI
#endif
public struct AutomaticPersistedQueryInterceptor: ApolloInterceptor {
public enum APQError: LocalizedError, Equatable {
case noParsedResponse
case persistedQueryNotFoundForPersistedOnlyQuery(operationName: String)
case persistedQueryRetryFailed(operationName: String)
public var errorDescription: String? {
switch self {
case .noParsedResponse:
return "The Automatic Persisted Query Interceptor was called before a response was received. Double-check the order of your interceptors."
case .persistedQueryRetryFailed(let operationName):
return "Persisted query retry failed for operation \"\(operationName)\"."
case .persistedQueryNotFoundForPersistedOnlyQuery(let operationName):
return "The Persisted Query for operation \"\(operationName)\" was not found. The operation is a `.persistedOnly` operation and cannot be automatically persisted if it is not recognized by the server."
}
}
}
public var id: String = UUID().uuidString
/// Designated initializer
public init() {}
public func interceptAsync<Operation: GraphQLOperation>(
chain: any RequestChain,
request: HTTPRequest<Operation>,
response: HTTPResponse<Operation>?,
completion: @escaping (Result<GraphQLResult<Operation.Data>, any Error>) -> Void) {
guard let jsonRequest = request as? JSONRequest,
jsonRequest.autoPersistQueries else {
// Not a request that handles APQs, continue along
chain.proceedAsync(
request: request,
response: response,
interceptor: self,
completion: completion
)
return
}
guard let result = response?.parsedResponse else {
// This is in the wrong order - this needs to be parsed before we can check it.
chain.handleErrorAsync(
APQError.noParsedResponse,
request: request,
response: response,
completion: completion
)
return
}
guard let errors = result.errors else {
// No errors were returned so no retry is necessary, continue along.
chain.proceedAsync(
request: request,
response: response,
interceptor: self,
completion: completion
)
return
}
let errorMessages = errors.compactMap { $0.message }
guard errorMessages.contains("PersistedQueryNotFound") else {
// The errors were not APQ errors, continue along.
chain.proceedAsync(
request: request,
response: response,
interceptor: self,
completion: completion
)
return
}
guard !jsonRequest.isPersistedQueryRetry else {
// We already retried this and it didn't work.
chain.handleErrorAsync(
APQError.persistedQueryRetryFailed(operationName: Operation.operationName),
request: jsonRequest,
response: response,
completion: completion
)
return
}
if Operation.operationDocument.definition == nil {
chain.handleErrorAsync(
APQError.persistedQueryNotFoundForPersistedOnlyQuery(operationName: Operation.operationName),
request: jsonRequest,
response: response,
completion: completion
)
return
}
// We need to retry this query with the full body.
jsonRequest.isPersistedQueryRetry = true
chain.retry(request: jsonRequest, completion: completion)
}
}