为什么我正在使用Apollo GraphQL
方法在项目中工作,并且工作正常。但是现在客户端需要使用Apollo API添加其他标头。但是添加标头后,API的响应将返回为 unAuthorized 。
我将标题添加为
let apolloAuth: ApolloClient = {
let configuration = URLSessionConfiguration.default
// Add additional headers as needed
configuration.httpAdditionalHeaders = ["Authorization" : self.singleTonInstance.token]
configuration.httpAdditionalHeaders = ["channel" : "mobile"]
let url = URL(string: "http://xxx/graphql")!
return ApolloClient(networkTransport: HTTPNetworkTransport(url: url, configuration: configuration))
}()
任何人都可以帮助我了解如何使用Apollo GraphQL添加标头。
答案 0 :(得分:7)
从Apollo Client v0.34.0及更高版本开始,先前提供的代码无效,因为它们重写了以前的工作方式。这对我有用。...有关更多信息,请考虑通过链接here浏览本文档。
class Network {
static let shared = Network()
private(set) lazy var apollo: ApolloClient = {
let client = URLSessionClient()
let cache = InMemoryNormalizedCache()
let store = ApolloStore(cache: cache)
let provider = NetworkInterceptorProvider(client: client, store: store)
let url = URL(string: "https://www.graphqlapi.com/")!
let transport = RequestChainNetworkTransport(interceptorProvider: provider,
endpointURL: url)
return ApolloClient(networkTransport: transport)
}()
}
class NetworkInterceptorProvider: LegacyInterceptorProvider {
override func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
var interceptors = super.interceptors(for: operation)
interceptors.insert(CustomInterceptor(), at: 0)
return interceptors
}
}
class CustomInterceptor: ApolloInterceptor {
// Find a better way to store your token this is just an example
let token = "YOUR TOKEN"
func interceptAsync<Operation: GraphQLOperation>(
chain: RequestChain,
request: HTTPRequest<Operation>,
response: HTTPResponse<Operation>?,
completion: @escaping (Result<GraphQLResult<Operation.Data>, Error>) -> Void) {
request.addHeader(name: "authorization", value: "Bearer: \(token)")
chain.proceedAsync(request: request,
response: response,
completion: completion)
}
}
答案 1 :(得分:6)
更新:“Apollo Client v0.41.0”和“Swift 5”的解决方案
我在使用 Apollo Client v0.41.0 和 Swift 5.0 时遇到了同样的问题,但上述解决方案均无效。经过数小时的试用,终于找到了解决方案。下面的解决方案是用 Apollo Client v0.41.0 和 Swift 5 测试的
import Foundation
import Apollo
class Network {
static let shared = Network()
private(set) lazy var apollo: ApolloClient = {
let cache = InMemoryNormalizedCache()
let store1 = ApolloStore(cache: cache)
let authPayloads = ["Authorization": "Bearer <<TOKEN>>"]
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = authPayloads
let client1 = URLSessionClient(sessionConfiguration: configuration, callbackQueue: nil)
let provider = NetworkInterceptorProvider(client: client1, shouldInvalidateClientOnDeinit: true, store: store1)
let url = URL(string: "https://<HOST NAME>/graphql")!
let requestChainTransport = RequestChainNetworkTransport(interceptorProvider: provider,
endpointURL: url)
return ApolloClient(networkTransport: requestChainTransport,
store: store1)
}()
}
class NetworkInterceptorProvider: LegacyInterceptorProvider {
override func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
var interceptors = super.interceptors(for: operation)
interceptors.insert(CustomInterceptor(), at: 0)
return interceptors
}
}
class CustomInterceptor: ApolloInterceptor {
func interceptAsync<Operation: GraphQLOperation>(
chain: RequestChain,
request: HTTPRequest<Operation>,
response: HTTPResponse<Operation>?,
completion: @escaping (Swift.Result<GraphQLResult<Operation.Data>, Error>) -> Void) {
request.addHeader(name: "Authorization", value: "Bearer <<TOKEN>>")
print("request :\(request)")
print("response :\(String(describing: response))")
chain.proceedAsync(request: request,
response: response,
completion: completion)
}
}
答案 2 :(得分:4)
现在可以接受的解决方案已经过时,因为HTTPNetworkTransport不再接受配置参数,而是直接接受looping
而不是URLSession
下面是一个示例,该示例如何在对Apollo Client的每个请求上发送授权标头,如果找到了该标头,则从Apollo Client(iOS)URLSessionConfiguration
中的UserDefaults中检索
version 0.21.0
答案 3 :(得分:3)
以前的答案很旧,现在可以通过委托来完成:
“此协议允许对请求进行事前验证,在修改请求之前可以退出紧急状态的功能以及使用其他标头修改URLRequest的功能。”
import Foundation
import Apollo
final class Network {
static let shared = Network()
private lazy var networkTransport: HTTPNetworkTransport = {
let transport = HTTPNetworkTransport(url: URL(string: "https://example.com/graphql")!)
transport.delegate = self
return transport
}()
private(set) lazy var apollo = ApolloClient(networkTransport: self.networkTransport)
}
extension Network: HTTPNetworkTransportPreflightDelegate {
func networkTransport(_ networkTransport: HTTPNetworkTransport, shouldSend request: URLRequest) -> Bool {
return true
}
func networkTransport(_ networkTransport: HTTPNetworkTransport, willSend request: inout URLRequest) {
var headers = request.allHTTPHeaderFields ?? [String: String]()
headers["Authorization"] = "Bearer \(YOUR_TOKEN)"
request.allHTTPHeaderFields = headers
}
}
这里是文档的链接,以获取更多详细信息:
答案 4 :(得分:2)
最后我找到了答案。通过以下方式添加标题,
let apolloAuth: ApolloClient = {
let configuration = URLSessionConfiguration.default
let token = UserDefaults.standard.value(forKey: "token")
// Add additional headers as needed
configuration.httpAdditionalHeaders = ["authorization":"\(token!)", "channel":"mobile"]
let url = URL(string: "http://xxxx/graphql")!
return ApolloClient(networkTransport: HTTPNetworkTransport(url: url, configuration: configuration))
}()
希望对某人有帮助。
答案 5 :(得分:1)
导入这两个元素
import UIKit
import Apollo
创建一个类 Network 并粘贴到源代码下方
struct Network {
static var request = Network()
private(set) lazy var apollo: ApolloClient = {
let cache = InMemoryNormalizedCache()
let store1 = ApolloStore(cache: cache)
let authPayloads = ["Authorization": "Bearer <TOKEN>"]
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = authPayloads
let client1 = URLSessionClient(sessionConfiguration: configuration, callbackQueue: nil)
let provider = NetworkInterceptorProvider(client: client1, shouldInvalidateClientOnDeinit: true, store: store1)
let url = URL(string: "http://xxx/graphql")!
let requestChainTransport = RequestChainNetworkTransport(interceptorProvider: provider,
endpointURL: url)
return ApolloClient(networkTransport: requestChainTransport,
store: store1)
}()
}
在 Network 类中添加 NetworkInterceptorProvider
class NetworkInterceptorProvider: LegacyInterceptorProvider {
override func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
var interceptors = super.interceptors(for: operation)
interceptors.insert(CustomInterceptor(), at: 0)
return interceptors
}
}
也在 Network 类中添加 CustomInterceptor
class CustomInterceptor: ApolloInterceptor {
func interceptAsync<Operation: GraphQLOperation>(
chain: RequestChain,
request: HTTPRequest<Operation>,
response: HTTPResponse<Operation>?,
completion: @escaping (Swift.Result<GraphQLResult<Operation.Data>, Error>) -> Void) {
request.addHeader(name: "Authorization", value: "Bearer <TOKEN>")
print("request :\(request)")
print("response :\(String(describing: response))")
chain.proceedAsync(request: request,
response: response,
completion: completion)
}
}
最后从 ViewController 调用这个方法
func todoQueryCloud(){
Network.request.apollo.fetch(query: ProgressionsQuery()){result in
// 3
switch result {
case .success(let graphQLResult):
guard let data = try? result.get().data else { return }
if graphQLResult.data != nil {
// 4
print("Loaded data \(String(describing: data.progressions))")
self.collectionView.reloadData()
}
case .failure(let error):
// 5
print("Error loading data \(error)")
}
}
}