如何在翻新(Android)中动态设置标题 [英] How to dynamically set headers in Retrofit (Android)

查看:88
本文介绍了如何在翻新(Android)中动态设置标题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的API使用的授权方案要求设置特殊的"X-Authorization"标头来验证请求.例如,此改造设置非常适合身份验证令牌为abc123:

I am using an API that uses an authorization scheme that requires a special "X-Authorization" header to be set to authenticate the request. For example, this Retrofit setup works perfectly for the user whose auth token is abc123:

@Headers("X-Authorization: abc123")
@GET("/posts")
Observable<List<Post>> get_posts();

我缓存了用户的X-Authorization令牌,因此可以访问它,但是,我不能只将其放在@Headers声明中.

I cache the user's X-Authorization token, so I have access to that, however, I can't just drop it in the @Headers declaration.

@Headers("X-Authorization: " + token)
@GET("/posts")
Observable<List<Post>> get_posts();

我在这里遇到编译错误:Error:(41, 34) error: element value must be a constant expression

I get a compile error here: Error:(41, 34) error: element value must be a constant expression

关于如何解决这个问题的任何想法?

Any ideas on how I could get around this?

推荐答案

自Retrofit 2.0起,您有两个选择

Since Retrofit 2.0 you have two options

1)使用OkHttp 2.2+,使用拦截器

1) Using OkHttp 2.2+ use Interceptor

在Http级别,您可以更好地控制请求,因此您可以执行一些操作,例如仅将标头应用于对特定端点发出的特定请求,等等.

At the Http level, you have more control over the request, so you could do things like applying headers only to a specific request made to a specific endpoint, and so on.

public class MyOkHttpInterceptor implements Interceptor {

@Override
public Response intercept(Chain chain) throws IOException {
    Request originalRequest = chain.request();
    if (!"/posts".contains(originalRequest.url()) ) {
        return chain.proceed(originalRequest);
    }

    String token = // get token logic 

    Request newRequest = originalRequest.newBuilder()
        .header("X-Authorization", token)
        .build();

    return chain.proceed(newRequest);
}

[...]

OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.networkInterceptors().add(new MyOkHttpInterceptor());
OkClient okClient = new OkClient(okHttpClient);
YourApi api = new RestAdapter.Builder()
            .setEndpoint(url)
            .setClient(okClient)
            .build()
            .create(YourApi.class);


编辑 : 添加 @JakeWarthon 注释作为另一种选择也是有效的.


Edit: Adding @JakeWarthon comment as another option as is also valid.

2)将 @Header 放在方法参数,并在调用时将其作为值传递.

2) Put @Header on a method parameter and pass it as a value when invoking.

来自文档 :

// Replaces the header with the the value of its target.
@GET("/")
void foo(@Header("Accept-Language") String lang, Callback<Response> cb);

标头参数可以为null,这会将其从请求中省略.传递列表或数组将为每个非空项目生成一个标题.

Header parameters may be null which will omit them from the request. Passing a List or array will result in a header for each non-null item.

注意:标头不会相互覆盖.所有具有相同名称的标头都将包含在请求中.

Note: Headers do not overwrite each other. All headers with the same name will be included in the request.

:该选项不应被视为Retrofit 2. *放弃了对拦截器的支持.

This option should not be considered as Retrofit 2.* dropped support for interceptors.

3)用户改造RequestInterceptor

从文档中: 在执行每个请求之前对其进行拦截,以添加其他数据.

您可以做类似

public class MyRetrofitInterceptor implements RequestInterceptor {

@Override
public void intercept(RequestFacade req) {
    String token = // get token logic 
    if (token != null) {
        req.addHeader("X-Authorization", token);
    }
}

[...]

YourApi api = new RestAdapter.Builder()
            .setEndpoint(url)
            .setRequestInterceptor(new MyRetrofitInterceptor())
            .build()
            .create(YourApi.class);

此方法的问题"是,拦截器将在所有端点上执行,因为它是在RestAdapter级别而不是每个端点上设置的.另外,RequestFacade不会公开有关请求的太多信息,因此没有机会在请求周围添加很多逻辑.

The "problem" with this approach is that the interceptor will get executed on all the endpoints, as it's set at the RestAdapter level, and not per endpoint. Also, the RequestFacade doesn't expose much information about the request, so no chance to add much logic around it.

这篇关于如何在翻新(Android)中动态设置标题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆