如何在Retrofit(Android)中动态设置标头

时间:2015-04-26 23:39:10

标签: android retrofit

我正在使用一种使用授权方案的API,该方案需要特殊的&#34; X-Authorization&#34;要设置标头以验证请求。例如,此Retrofit设置适用于身份验证令牌为@Headers("X-Authorization: " + token) @GET("/posts") Observable<List<Post>> get_posts(); 的用户:

Error:(41, 34) error: element value must be a constant expression

我缓存了用户的X-Authorization令牌,所以我可以访问它,但是,我不能把它放在@Headers声明中。

storage: file
 def store_dir
    "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
  end

我在这里收到编译错误: mount_uploader :link_to_video_proposal, VideoUploader

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

4 个答案:

答案 0 :(得分:76)

自Retrofit 2.0以来,您有两个选择

1)使用OkHttp 2.2+使用live demo

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

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

<强> 修改 : 添加Interceptor注释作为另一个选项也是有效的。

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

来自@Header

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);

标头参数可以为null,这将从请求中省略它们。传递List或数组将导致每个非null项的标题。

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

编辑: 此选项不应被视为Retrofit 2. *不再支持拦截器。

3)用户改造RequestInterceptor

来自文档: 在执行之前拦截每个请求以添加其他数据。

您可以执行类似

的操作
RequestFacade

这种方法的“问题”是拦截器将在所有端点上执行,因为它是在RestAdapter级别设置的,而不是每个端点。此外,{{1}}没有公开有关请求的大量信息,因此没有机会在其周围添加太多逻辑。

答案 1 :(得分:8)

在参数中传递标题会很有帮助。请查看以下代码;

 @GET("/posts")
Observable<JsonElement> getDataFromService(
        @HeaderMap Map<String, String> headers,
        @QueryMap HashMap<String, Object> queryParams
);

        hashMap1.put("Authorization", token);
    return ApiService.getAPI_test().getDataFromService(hashMap1, url, hashMap)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribeOn(Schedulers.io());

答案 2 :(得分:2)

可以使用@Header批注动态更新请求标头。必须为@Header提供相应的参数。如果该值为null,则标题将被省略。否则,将对值调用toString,并使用结果。

@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

答案 3 :(得分:0)

翻新2中的动态标题

在为翻新2添加动态标题方面,我付出了很多努力。

我经历了很多博客和StackOver流。每个人都展示了拦截器的例子。

这不是明智的选择,只是对于一个API调用,我们需要做很多工作。

您只需添加 @HeaderMap 作为fun的参数。我已经以非常简单的方式完成了:-

在科特林

    val headers = HashMap<String, String>()
    headers["KEY_AUTHORIZATION"] = "paste AUTHORIZATION value here"
    headers["KEY_TOKEN"] = "paste TOKEN value here"

    val jsonObject= JsonObject()

I am passing here header and other data also
Calling of fun:-

postEvent(headers,jsonObject)

API Declaration 

    @POST("/v1/post_data")
    fun postEvent(@HeaderMap headers: Map<String, String>, @Body jsonObject: JsonObject): Call<JsonObject>

API Declaration with RxAndroid

    @POST("/v1/post_data")
    fun postEvent(@HeaderMap headers: Map<String, String>, @Body jsonObject: JsonObject): Single<JsonObject>

这里的第二个参数我有JsonObject。您可以用任何需要通过的东西代替,也可以将其删除。

在Java中

 HashMap<String, String> headers = new HashMap<String, String>();
    headers.put("KEY_AUTHORIZATION","paste AUTHORIZATION value here");
    headers.put("KEY_TOKEN", "paste TOKEN value here");

    JsonObject jsonObject= new JsonObject();

I am passing here header and other data also

Calling of fun:-
postEvent(headers,jsonObject);

    API Declaration 
    @POST("/v1/post_data")
    Call<JsonObject> postEvent(@HeaderMap Map<String, String> headers, @Body JsonObject jsonObject);

API Declaration with RxAndroid

    @POST("/v1/post_data")
    Single<JsonObject> postEvent(@HeaderMap Map<String, String> headers, @Body JsonObject jsonObject);

这里的第二个参数我有JsonObject。您可以用任何需要通过的东西代替,也可以将其删除。