You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:53:46