将 Apollo iOS 客户端 GraphQL 查询变量和 url 记录到控制台?
Log Apollo iOS Client GraphQL query variables and url to console?
我想在调用查询时将我的 Apollo iOS 客户端 GraphQL 查询的 url 打印到 Xcode 控制台。
扩展 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 来获取同样的信息,这也将支持突变和订阅。
您不需要编写 swift 代码来提取 QueryName。
使用 Proxyman,例如 Charles Proxy。默认情况下,它将在列上显示 QueryName。
参考:https://docs.proxyman.io/advanced-features/graphql
根据 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)
}()
我想在调用查询时将我的 Apollo iOS 客户端 GraphQL 查询的 url 打印到 Xcode 控制台。
扩展 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 来获取同样的信息,这也将支持突变和订阅。
您不需要编写 swift 代码来提取 QueryName。
使用 Proxyman,例如 Charles Proxy。默认情况下,它将在列上显示 QueryName。
参考:https://docs.proxyman.io/advanced-features/graphql
根据 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)
}()