如何在apollo-android中自定义请求头及读取响应头令牌
解决Apollo-Android动态请求头与响应头令牌读取问题
我刚好之前也遇到过类似的场景,这两个问题其实都可以通过Apollo-Android本身的API来解决,不需要依赖全局的OkHttp拦截器,完全能满足你不同请求用不同头的需求,具体方案如下:
一、为单个请求动态添加自定义请求头
因为你需要为不同请求设置不同的头,全局拦截器确实不合适,Apollo-Android提供了两种灵活的方式来逐个请求控制请求头:
1. 发起请求时通过ApolloRequest.Builder添加
在构建ApolloCall的过程中,你可以直接通过requestBuilder()来动态添加任意请求头,每个请求都可以单独设置:
// 示例:针对某个查询请求添加Authorization头 val myQueryCall = apolloClient.query(MyGraphQLQuery()) .requestBuilder() .addHttpHeader("Authorization", "Bearer ${yourDynamicToken}") .addHttpHeader("X-Custom-Header", "custom-value-for-this-request") // 还可以加多个自定义头 .build() // 执行请求 myQueryCall.enqueue(object : ApolloCall.Callback<MyGraphQLQuery.Data>() { // 处理响应和错误... })
2. 在GraphQL操作定义中使用@Header注解(支持动态变量)
如果你希望把请求头和特定的GraphQL操作绑定,可以在操作定义时添加@Header注解,然后在发起请求时传入动态值:
# 在你的.graphql文件中定义查询时添加@Header @Header(name = "Authorization", value = "{authToken}") query UserProfile($userId: ID!) { user(id: $userId) { id name } }
然后在代码中发起请求时,通过variable()传入动态的令牌值:
val profileCall = apolloClient.query(UserProfileQuery(userId = "123")) .variable("authToken", "Bearer ${yourDynamicToken}") .build()
如果需要复用这类逻辑,还可以封装一个扩展函数,让代码更简洁:
fun <D : Operation.Data> ApolloCall<D>.withAuthToken(token: String): ApolloCall<D> { return this.requestBuilder() .addHttpHeader("Authorization", "Bearer $token") .build() } // 使用时直接链式调用 apolloClient.query(UserProfileQuery(userId = "123")) .withAuthToken(userSpecificToken) .enqueue(...)
二、读取响应头中的认证令牌
Apollo-Android的Response对象允许你获取底层的OkHttpResponse实例,通过它就能轻松读取响应头里的令牌:
1. 异步请求方式(enqueue)
apolloClient.query(LoginQuery(username = "user", password = "pass")) .enqueue(object : ApolloCall.Callback<LoginQuery.Data>() { override fun onResponse(response: Response<LoginQuery.Data>) { // 通过rawResponse()获取OkHttp的原始响应 val authToken = response.rawResponse()?.header("X-Auth-Token") authToken?.let { // 这里可以把令牌保存到SharedPreferences或者其他本地存储 saveTokenToLocal(it) } } override fun onFailure(e: ApolloException) { // 处理请求失败逻辑 } })
2. 协程/同步请求方式(await)
如果你用协程开发,可以直接用await()获取响应,然后读取头:
coroutineScope.launch { try { val response = apolloClient.query(LoginQuery(username = "user", password = "pass")).await() val authToken = response.rawResponse()?.header("X-Auth-Token") authToken?.let { saveTokenToLocal(it) } } catch (e: ApolloException) { // 处理异常 } }
这样不管是动态设置请求头,还是读取响应头里的令牌,都能完美解决你的问题,而且完全是针对单个请求做控制,不会影响其他请求的头设置。
内容的提问来源于stack exchange,提问作者Vlad Kudoyar
相关产品推荐
相关产品推荐

