Привет, я работаю над проектом с методом Apollo GraphQL, и он работает нормально. Но теперь клиенту требуется добавить дополнительный заголовок с API-интерфейсом Apollo. Но после добавления заголовка ответ API возвращается как неавторизованный.
Я добавляю заголовок как,
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.
вы нашли какое-нибудь решение?
Пожалуйста, обратитесь к моему ответу.





Наконец я нашел ответ. Добавьте заголовок следующим образом:
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))
}()
Надеюсь, это поможет кому-то.
он перестает работать с версии 0.34, больше нет HTTPNetworkTransport
Принятое решение теперь устарело, поскольку HTTPNetworkTransport больше не принимает аргумент конфигурации, вместо этого принимает URLSession напрямую, а не URLSessionConfiguration
Вот пример того, как отправлять заголовок авторизации при каждом запросе к клиенту Apollo, извлекая его, если он найден, из UserDefaults в version 0.21.0 клиента Apollo (iOS).
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))
)
}()
}
Предыдущие ответы устарели, теперь это делается через делегата:
"This protocol allows pre-flight validation of requests, the ability to bail out before modifying the request, and the ability to modify the URLRequest with things like additional headers."
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/
Я получаю эти ошибки Cannot find type 'HTTPNetworkTransport' in scope и Cannot find type 'HTTPNetworkTransportPreflightDelegate' in scope любую помощь? Я использую Appoloclient v0.34.1.
@GB Я проверил документы по ссылке выше, и они устарели от HTPPNetworkTransport. Это все еще можно сделать с помощью «LegacyInterceptorProvider», или вы можете изучить новый протокол: NetworkTransport.
Я предоставил решение, которое вы можете посмотреть на него.
Начиная с 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)
}
}
ОБНОВЛЕНИЕ: Решение для «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)
}
}
Спасибо! Это единственное решение, которое работает с Apollo 0.42.0.
@Camath Jeevan Я попробовал это решение с версией Apollo 0.43.0, и оно выдает ошибку сбоя reposne как сбой(Apollo.LegacyParsingInterceptor.LegacyParsingError.couldNotParseToLegacyJSON (данные: 1839 байтов)), пожалуйста, предложите мне, что я могу сделать дальше
@JochenHolzer Я тоже пробовал тот же синтаксис кода, но запрос дает мне HTML в блоке сбоя. Не могли бы вы помочь мне решить эту проблему Заголовок Apollo GraphQL всегда дает сбой в iOS Swift
@Princess Возможно, в ответе HTML есть сообщение об ошибке. На вашем месте я бы спросил команду разработчиков конечной точки, какая информация о вашем неудачном запросе содержится в файлах журнала сервера.
@JochenHolzer Я использую Shopify GraphQL Admin API для получения информации о заказе клиента из магазина Shopify. Тот же URL-запрос работает с клиентом Android Apollo.
Это решение сработало для меня. Спасибо @ChamathJeevan
Импортируйте эти два элемента
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)
}()
}
добавить 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
}
}
добавить 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)")
}
}
}
У меня это не работает. Я задал новый вопрос Заголовок Apollo GraphQL всегда дает сбой в iOS Swift, пожалуйста, проверьте это.
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
}
}
Вы пытались установить заголовок «Bearer <token>» вместо «<token>»? Какой метод авторизации использует ваш сервер? У вас есть рабочий оператор cURL для сервера, который использует токен авторизации?