如何在Apollo GraphQL:iOS中添加header

krcsximq  于 12个月前  发布在  iOS
关注(0)|答案(9)|浏览(137)

Hy我在一个项目中使用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添加标题。

bwntbbo3

bwntbbo31#

更新:“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: DefaultInterceptorProvider {
    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)
    }
}

字符串

mm9b1k5b

mm9b1k5b2#

从Apollo Client v0.34.0及以上版本开始,之前提供的代码将无法工作,因为他们重写了它以前的工作方式。以下是对我有效的代码.有关更多信息,请参阅此处链接中的文档。

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)
    }
}

字符串

fjaof16o

fjaof16o3#

最后我找到了答案。按以下方式添加标题,

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))

    }()

字符串
希望它能帮助某人。

6jygbczu

6jygbczu4#

接受的解决方案现在已经过时,因为HTTPNetworkTransport不再接受配置参数,而是直接接受URLSession而不是URLSessionConfiguration
下面是一个示例,如何在每个请求上向Apollo客户端发送授权头,如果找到,则从Apollo客户端(iOS)的version 0.21.0中的Username中检索它。

import Foundation
import Apollo

class Network {
    static let shared = Network()

    private(set) lazy var apollo: ApolloClient = {
        let token = UserDefaults.standard.string(forKey: "accessToken") ?? ""
        let url = URL(string: "http://localhost:4000/graphql")!

        let configuration = URLSessionConfiguration.default

        configuration.httpAdditionalHeaders = ["authorization": "Bearer \(token)"]

        return ApolloClient(
            networkTransport: HTTPNetworkTransport(url: url, session: URLSession(configuration: configuration))
        )
    }()
}

字符串

zbsbpyhn

zbsbpyhn5#

更新:Apollo Client v0.34.0后不推荐使用此解决方案

以前的答案是旧的,现在通过委托完成:
该协议允许对请求进行飞行前验证,能够在修改请求之前进行保释,并能够使用附加标头等内容修改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
    }
}

字符串
这里有一个链接到文档的更多细节:
https://www.apollographql.com/docs/ios/initialization/

bqujaahr

bqujaahr6#

导入这两个元素

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)
}


}
finally从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)")
        }
    }
}

fjaof16o

fjaof16o7#

NetworkInterceptorProvider:LegacyInterceptorProvider更改为“DefaultInterceptorProvider”

class NetworkInterceptorProvider: DefaultInterceptorProvider {
override func interceptors<Operation: GraphQLOperation>(for operation: Operation) -> [ApolloInterceptor] {
    var interceptors = super.interceptors(for: operation)
    interceptors.insert(CustomInterceptor(), at: 0)
    return interceptors
}

字符串
}

q9rjltbz

q9rjltbz8#

更新了Apollo 1.6.1的解决方案

import Foundation
import Apollo

class DataCoordinator: NSObject {
    // MARK: Variables
    static let shared: DataCoordinator = DataCoordinator()
    private(set) lazy var apolloClient: ApolloClient = {
        let cache = InMemoryNormalizedCache()
        let store = ApolloStore(cache: cache)
        let authPayloads = ["Authorization": "Bearer \(token)"]
        let configuration = URLSessionConfiguration.default
        configuration.httpAdditionalHeaders = authPayloads
        let client = URLSessionClient(sessionConfiguration: configuration, callbackQueue: nil)
        let provider = NetworkInterceptorProvider(store: store, client: client)
        let url = URL(string: "https://xxxxxxxxx/graphql")!
        let requestChainTransport = RequestChainNetworkTransport(interceptorProvider: provider, endpointURL: url)
        return ApolloClient(networkTransport: requestChainTransport, store: store)
    }()
}

struct NetworkInterceptorProvider: InterceptorProvider {
    // These properties will remain the same throughout the life of the `InterceptorProvider`, even though they
    // will be handed to different interceptors.
    private let store: ApolloStore
    private let client: URLSessionClient
    
    init(store: ApolloStore,
         client: URLSessionClient) {
        self.store = store
        self.client = client
    }
    
    func interceptors<Operation>(for operation: Operation) -> [ApolloInterceptor] {
        return [
            MaxRetryInterceptor(),
            CacheReadInterceptor(store: self.store),
            NetworkFetchInterceptor(client: self.client),
            ResponseCodeInterceptor(),
            JSONResponseParsingInterceptor(),
            AutomaticPersistedQueryInterceptor(),
            CacheWriteInterceptor(store: self.store)
        ]
    }
}

字符串
快乐编程

xtupzzrd

xtupzzrd9#

我一直在学习https://www.apollographql.com/docs/ios/tutorial/tutorial-execute-first-query的教程
如果你的目标只是添加一个自定义头,那么最简单的方法就是

import Apollo
import Foundation

class Network {
    static let shared = Network()

    private(set) lazy var apollo: ApolloClient = {
        let url = URL(string: "https://example.com/v1/graphql")!

        let configuration = URLSessionConfiguration.default
        configuration.httpAdditionalHeaders = ["Authorization": "Bearer token"] // Add your headers here

        let client = URLSessionClient(sessionConfiguration: configuration)
        let store = ApolloStore(cache: InMemoryNormalizedCache())
        let provider = DefaultInterceptorProvider(client: client, store: store)
        let networkTransport = RequestChainNetworkTransport(interceptorProvider: provider, endpointURL: url)

        return ApolloClient(networkTransport: networkTransport, store: store)
    }()
}

字符串
希望能对大家有所帮助!

相关问题