【发布时间】:2021-04-24 02:57:10
【问题描述】:
我想在调用查询时将我的 Apollo iOS 客户端 GraphQL 查询的 url 打印到 Xcode 控制台。
【问题讨论】:
我想在调用查询时将我的 Apollo iOS 客户端 GraphQL 查询的 url 打印到 Xcode 控制台。
【问题讨论】:
您无需编写 swift 代码即可提取 QueryName。
使用 Proxyman,例如 Charles Proxy。默认情况下,它将在列上显示 QueryName。
【讨论】:
根据Apollo iOS Client docs,可以在自定义拦截器提供程序中添加日志拦截器。
我使用来自 DefaultInterceptorProvider 的代码创建了一个自定义拦截器提供程序,并包含了日志拦截器。
import Apollo
class InterceptorProviderWithLogging: InterceptorProvider {
private let client: URLSessionClient
private let store: ApolloStore
private let shouldInvalidateClientOnDeinit: Bool
public init(client: URLSessionClient = URLSessionClient(),
shouldInvalidateClientOnDeinit: Bool = true,
store: ApolloStore) {
self.client = client
self.shouldInvalidateClientOnDeinit = shouldInvalidateClientOnDeinit
self.store = store
}
deinit {
if self.shouldInvalidateClientOnDeinit {
self.client.invalidate()
}
}
open func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
return [
MaxRetryInterceptor(),
CacheReadInterceptor(store: self.store),
RequestLoggingInterceptor(), // added logging interceptor
NetworkFetchInterceptor(client: self.client),
ResponseCodeInterceptor(),
JSONResponseParsingInterceptor(cacheKeyForObject: self.store.cacheKeyForObject),
AutomaticPersistedQueryInterceptor(),
CacheWriteInterceptor(store: self.store),
]
}
open func additionalErrorInterceptor<Operation: GraphQLOperation>(for operation: Operation) -> ApolloErrorInterceptor? {
return nil
}
}
class RequestLoggingInterceptor: ApolloInterceptor {
func interceptAsync<Operation: GraphQLOperation>(
chain: RequestChain,
request: HTTPRequest<Operation>,
response: HTTPResponse<Operation>?,
completion: @escaping (Result<GraphQLResult<Operation.Data>, Error>) -> Void) {
if let url = try? request.toURLRequest().url?.absoluteString.removingPercentEncoding {
if let variables = request.operation.variables {
print("\(request.operation.operationName) parameters: \(variables) \(url)")
} else {
print("\(request.operation.operationName) \(url)")
}
}
chain.proceedAsync(request: request, response: response, completion: completion)
}
}
我在请求链网络传输中使用自定义拦截器提供程序。
private(set) lazy var apolloClient: ApolloClient = {
let store = ApolloStore()
let interceptorProvider = InterceptorProviderWithLogging(store: store)
let requestChainTransport = RequestChainNetworkTransport(
interceptorProvider: interceptorProvider,
endpointURL: url,
additionalHeaders: [:],
autoPersistQueries: false,
requestBodyCreator: ApolloRequestBodyCreator(),
useGETForQueries: true,
useGETForPersistedQueryRetry: false
)
return ApolloClient(networkTransport: requestChainTransport, store: store)
}()
【讨论】:
扩展 GraphQLQuery 提供对操作名称、操作 ID 和变量的访问,这些可用于构建 url。我还打印出查询的操作名称和变量。
extension GraphQLQuery {
func printInfo() {
if let variables = self.variables?.JSONString {
let cleanedVariables = variables.replacingOccurrences(of: "\\", with: "")
print("GraphQL Query: \(self.operationName) \(variables))")
if let operationID = self.operationIdentifier {
let url = "\(GraphQLClient.shared.url)?extensions={\"persistedQuery\":{\"sha256Hash\":\"\(operationID)\",\"version\":1}}&id=\(operationID)&operationName=\(self.operationName)&variables=\(cleanedVariables)"
print("GraphQL URL", url)
}
} else {
print("GraphQL Query: \(self.operationName)")
if let operationID = self.operationIdentifier {
let url = "\(GraphQLClient.shared.url)?extensions={\"persistedQuery\":{\"sha256Hash\":\"\(operationID)\",\"version\":1}}&id=\(operationID)&operationName=\(self.operationName)"
print("GraphQL URL", url)
}
}
}
}
用法:
let standingsQuery = GetStandingsForSportQuery(sportID: sportIDInt, season: season)
standingsQuery.printInfo()
示例输出:
GraphQL Query: getStandingsForSport {"sportID":7,"season":"2020"})
GraphQL URL: https://api.company.com/graphql?extensions={"persistedQuery":{"sha256Hash":"932b414fdadb641f95659d6c61aa29d6d6b0ccf1fa704a0ace751187b90b8cac","version":1}}&id=932b414fdadb641f95659d6c61aa29d6d6b0ccf1fa704a0ace751187b90b8cac&operationName=getStandingsForSport&variables={"sportID":1,"season":"2020"}
此示例中的 url 格式可能不是典型的,因为我们使用的是持久化查询。我使用 Charles 代理查看发送的实际 url,所以我知道格式。
您还可以扩展 GraphQLOperation 而不是 GraphQLQuery 来获取相同的信息,这也将支持突变和订阅。
【讨论】: