我有自定义拦截器进行身份验证:
@Named("authInterceptor")
@Provides
@Singleton
fun providesAuthInterceptor(preferencesManager: PreferencesManager): Interceptor {
return Interceptor { chain ->
val newBuilder = chain.request().newBuilder()
newBuilder.addHeader("access-token", preferencesManager.getAccessToken())
val request = newBuilder.build()
return@Interceptor chain.proceed(request)
}
}
但我有一些不需要auth标头的电话。
我希望在我的服务中拥有:
interface NetService {
@NEEDAUTH
@GET("users")
fun getAllShops(key: String): Single<SomeResponse>
@FormUrlEncoded
@POST("users")
fun register(@Field("nickname") nickname: String): Single<SomeResponse>
}
因此,第一个调用将使用authInterceptor,第二个调用将不使用它。
答案 0 :(得分:5)
从Retrofit 2.6.0版本开始,您可以使用如下标记字段在OkHttp Interceptor中获取批注:
response.request.tag(Invocation::class.java)?.method()?.getAnnotation(YourAnnotation::class.java)
然后在拦截器中,您可以验证请求是否带有注释。
改造变更日志:
新功能:@Tag参数注释,用于在基础OkHttp Request对象上设置标签。可以在CallAdapters或OkHttp拦截器中读取这些内容,以进行跟踪,分析,各种行为等。
答案 1 :(得分:2)
我有类似的要求,我找到的是注释可以在Converter.Factory:requestBodyConverter()
中阅读,
Converter.Factory:responseBodyConverter()
和CallAdapter.Factory.get()
。
我还发现有两篇文章作为每种方式的实施示例。
我们将使用Retrofit提供的gson转换器(GsonConverterFactory)并稍微修改它以在GsonResponseBodyConverter.class中包含一个侦听器来处理http响应解析。
在GsonCacheableConverter
中,它会覆盖responseBodyConverter()
以保留使用@Cacheable
标记的回复。
我们在CallAdapter.Factory中读取了注释,当在CallAdapter中创建请求时,我们将在某个地图中存储此类请求的一些信息,以便稍后在某些拦截器中识别它。
它使用自定义CallAdapter来获取注释@Authenticated
,并将数据放入地图中,以后会在拦截器中进行解析。
我认为requestBodyConverter()
和CallAdapter
更接近您的要求。
虽然如果你不坚持自定义注释,我认为现在最简单的方法是在api界面添加自定义标头,然后在拦截器中读取并删除它。
即,将@Headers("needauth: 1")
添加到您的服务中,然后使用chain.request().header("needauth")
获取该值。
答案 2 :(得分:0)
Interceptor
是OkHttp
中存在的概念,Retrofit
对它们一无所知。
您需要做的是拥有两个OkHttp
个客户,其各自的实例为Retrofit
。
是否需要身份验证标头将决定要注入哪个实例。
答案 3 :(得分:0)
基于Max Cruz answer。确实尝试在此处发表评论,但它看起来太难看了,因为不知道如何制作多行。
我正在用作扩展功能:
fun <T : Annotation> Request.getCustomAnnotation(annotationClass: Class<T>): T? = this.tag(Invocation::class.java)?.method()?.getAnnotation(annotationClass)
然后您可以像这样使用
: request.getCustomAnnotation(YourAnnotation::class.java)