问题描述
我的 Retrofit 2(当前为 2.0.2
)客户端需要向请求添加自定义标头.
My Retrofit 2 (2.0.2
currently) client needs to add custom headers to requests.
我正在使用 Interceptor
将这些标头添加到所有请求中:
I'm using an Interceptor
to add these headers to all requests:
OkHttpClient httpClient = new OkHttpClient();
httpClient.networkInterceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
final Request request = chain.request().newBuilder()
.addHeader("CUSTOM_HEADER_NAME_1", "CUSTOM_HEADER_VALUE_1")
.addHeader("CUSTOM_HEADER_NAME_2", "CUSTOM_HEADER_VALUE_2")
...
.addHeader("CUSTOM_HEADER_NAME_N", "CUSTOM_HEADER_VALUE_N")
.build();
return chain.proceed(request);
}
});
Retrofit retrofitClient = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(httpClient)
.build();
我一直想添加一些标头,但我只需要根据特定端点的要求添加一些标头,例如用户是否需要进行身份验证.
Some headers I always want to add, but some headers I only need to add based on requirements of that specific endpoint, for example whether the user needs to be authenticated or not.
我希望能够在 api 级别控制它,例如使用注释,例如:
I'd like to have the ability to control that at the api level, for example using an annotation, something like:
public interface MyApi {
@NO_AUTH
@POST("register")
Call<RegisterResponse> register(@Body RegisterRequest data);
@GET("user/{userId}")
Call<GetUserResponse> getUser(@Path("userId") String userId);
}
当向register
发送请求时,不需要添加认证令牌,但缺少@NO_AUTH
注解的请求会有令牌头.
When sending a request to register
there's no need to add the authentication token, but requests who lack the @NO_AUTH
annotation will have the token header.
据我所知,Retrofit 2 不支持自定义注释,虽然我找到了 Retrofit 2 的自定义注解,似乎有点太多了.
From what I understand Retrofit 2 doesn't support custom annotations, and while I found this workaround for Custom Annotations with Retrofit 2, it's seems a bit too much.
我想避免为每个请求传递这些标头的需要,例如:
I'd like to avoid the need to pass these headers per request, like:
public interface MyApi {
@POST("register")
Call<RegisterResponse> register(@Body RegisterRequest data);
@GET("user/{userId}")
Call<GetUserResponse> getUser(@Header("AuthToken") String token, @Path("userId") String userId);
}
每次调用该方法而不是在拦截器中执行它时都感觉多余(因为我可以静态访问标头值).
我只是需要在我的 Interceptor.intercept
实现中知道这个特定的请求是否应该有一个特定的标头.
It just feels redundant to do it every time I call the method instead of doing it in the interceptor (since I have access to the header values statically).
I just somehow need to know in my Interceptor.intercept
implementation whether or not this specific request should have a specific header(s).
知道如何使这项工作成功吗?
我更喜欢通用解决方案,而不仅仅是针对身份验证令牌的情况,但也欢迎使用特定的解决方案.谢谢
Any idea how I can make this work?
I prefer a generic solution and not just for the auth token case, but a specific solution is welcome as well.Thanks
推荐答案
我想出了一个非常简单和优雅(在我看来)的解决方案来解决我的问题,并且可能适用于其他场景.
I came up with a very simple and elegant (in my opinion) solution to my problem, and probably for other scenarios.
我使用 Headers
批注来传递我的自定义批注,并且由于 OkHttp 要求它们遵循 Name: Value
格式,因此我决定我的格式为:@:ANNOTATION_NAME.
I use the Headers
annotation to pass my custom annotations, and since OkHttp requires that they follow the Name: Value
format, I decided that my format will be: @: ANNOTATION_NAME
.
所以基本上:
public interface MyApi {
@POST("register")
@HEADERS("@: NoAuth")
Call<RegisterResponse> register(@Body RegisterRequest data);
@GET("user/{userId}")
Call<GetUserResponse> getUser(@Path("userId") String userId);
}
然后我可以拦截请求,检查我是否有名称为@
的注解.如果是这样,我会获取该值并从请求中删除标头.
即使您想要多个自定义注释",这也很有效:
Then I can intercept the request, check whether I have an annotation with name @
. If so, I get the value and remove the header from the request.
This works well even if you want to have more than one "custom annotation":
@HEADERS({
"@: NoAuth",
"@: LogResponseCode"
})
以下是提取所有这些自定义注释"并将其从请求中删除的方法:
Here's how to extract all of these "custom annotations" and remove them from the request:
new OkHttpClient.Builder().addNetworkInterceptor(new Interceptor() {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
List<String> customAnnotations = request.headers().values("@");
// do something with the "custom annotations"
request = request.newBuilder().removeHeader("@").build();
return chain.proceed(request);
}
});
这篇关于Retrofit 2 - 在 api 级别添加标题的优雅方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!