Apollo GraphQL iOS:认证查询请求未发送问题求助
排查未发送的带认证GraphQL请求(iOS Apollo)
问题背景
无GraphQL经验,尝试发起带认证的GraphQL查询,但请求未发送:Proxyman无记录,无任何成功/失败回调。已参照官方逻辑编写代码,断点显示拦截器已加入NetworkChain,代码生成验证正常。
相关代码实现
Network类与拦截器代码
public final class Network { public static let shared = Network() public static func authenticatedApollo(_ authenticationData: GraphQLAuthenticationData) -> ApolloClient { let client = URLSessionClient() let cache = InMemoryNormalizedCache() let store = ApolloStore(cache: cache) let provider = NetworkAuthenticatedInterceptorProvider(client: client, store: store, authenticationData: authenticationData) let url = URL(string: "my instance url")! let transport = RequestChainNetworkTransport(interceptorProvider: provider, endpointURL: url) return ApolloClient(networkTransport: transport, store: store) } } private class AuthorizationInterceptor: ApolloInterceptor { public var id: String private let authenticationData: GraphQLAuthenticationData init(id: String = UUID().uuidString, authenticationData: GraphQLAuthenticationData) { self.id = id self.authenticationData = authenticationData } func interceptAsync<Operation>(chain: RequestChain, request: HTTPRequest<Operation>, response: HTTPResponse<Operation>?, completion: @escaping (Result<GraphQLResult<Operation.Data>, Error>) -> Void) where Operation: GraphQLOperation { request.addHeader(name: "Authorization", value: authenticationData.token) // adding other headers chain.proceedAsync(request: request, response: response, interceptor: self, completion: completion) } } private class NetworkAuthenticatedInterceptorProvider: DefaultInterceptorProvider { private let authenticationData: GraphQLAuthenticationData init(client: URLSessionClient = URLSessionClient(), shouldInvalidateClientOnDeinit: Bool = true, store: ApolloStore, authenticationData: GraphQLAuthenticationData) { self.authenticationData = authenticationData super.init(client: client, shouldInvalidateClientOnDeinit: shouldInvalidateClientOnDeinit, store: store) } override func interceptors<Operation>(for operation: Operation) -> [ApolloInterceptor] where Operation: GraphQLOperation { var interceptors = super.interceptors(for: operation) let interceptor = AuthorizationInterceptor(authenticationData: authenticationData) interceptors.insert(interceptor, at: 0) return interceptors } }
查询执行代码
Network.authenticatedApollo(authenticationData).fetch(query: DemoAuthenticatedCallQuery(), cachePolicy: .fetchIgnoringCacheData) {result in switch result { case .success(let data): print("🛸 authenticated data: <...>)") case .failure(let error): print("🛸 authenticated error: \(error.localizedDescription)") } }
排查建议
- 验证目标URL有效性:确认
"my instance url"是完整且可连通的地址,无拼写错误、缺失端口或路径。可直接在浏览器/Postman中测试该URL的连通性。 - 修复ApolloClient生命周期问题:当前
authenticatedApollo每次调用都会生成新的ApolloClient实例,执行fetch后无强引用持有该实例,会导致客户端被提前释放,请求静默取消。需在调用类中持有强引用:// 在调用类中添加属性 private var apolloClient: ApolloClient? // 执行请求时 apolloClient = Network.authenticatedApollo(authenticationData) apolloClient?.fetch(query: DemoAuthenticatedCallQuery(), cachePolicy: .fetchIgnoringCacheData) { result in // 回调处理逻辑 } - 添加拦截器执行日志:在
AuthorizationInterceptor的interceptAsync方法中添加日志,确认拦截器是否真正执行,同时检查请求头是否正确添加:func interceptAsync<Operation>(chain: RequestChain, request: HTTPRequest<Operation>, response: HTTPResponse<Operation>?, completion: @escaping (Result<GraphQLResult<Operation.Data>, Error>) -> Void) where Operation: GraphQLOperation { print("AuthorizationInterceptor triggered, token: \(authenticationData.token)") request.addHeader(name: "Authorization", value: authenticationData.token) print("Request headers: \(request.allHTTPHeaderFields ?? [:])") chain.proceedAsync(request: request, response: response, interceptor: self, completion: completion) } - 检查URLSession配置:默认
URLSessionClient使用系统默认配置,若存在代理、SSL校验或超时设置问题,可能导致请求静默失败。可自定义配置传入:let configuration = URLSessionConfiguration.default configuration.timeoutIntervalForRequest = 30 let client = URLSessionClient(sessionConfiguration: configuration) - 确认认证数据格式:检查
authenticationData.token是否为空,以及格式是否符合服务端要求(比如Bearer Token需要带Bearer前缀)。 - 启用Apollo调试日志:创建
RequestChainNetworkTransport时开启调试日志,查看请求的完整流程:let transport = RequestChainNetworkTransport( interceptorProvider: provider, endpointURL: url, debugLog: { print("Apollo debug: \($0)") } ) - 检查App网络权限:确认Info.plist中配置了正确的网络权限(如非HTTPS地址需配置
NSAppTransportSecurity,iOS 14+需对应权限配置)。
内容的提问来源于stack exchange,提问作者invalidArgument
相关产品推荐
相关产品推荐

