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

Retrofit 2拦截器修改401响应体无效的问题求助

解决Retrofit 2拦截401响应后修改响应体不生效的问题

我刚帮你捋了下这个问题,核心原因是Retrofit依赖的OkHttp里的ResponseBody是基于流的一次性对象——你直接调用response.body().contentType()的时候,已经触发了原始响应体流的读取,流被消耗后就无法再被下游处理,导致你替换的新响应体根本没生效!另外,你还没关闭原始响应体,容易造成资源泄漏。

给你修正后的完整Interceptor代码,每一步都加了注释:

@Override
public Response intercept(Chain chain) throws IOException {
    // 构建带授权头的请求
    Request original = chain.request();
    Request request = original.newBuilder()
            .header("authorization", getAccessToken(context))
            .build();
    
    // 执行请求获取响应
    Response response = chain.proceed(request);

    if (response.code() == 401) {
        // 1. 必须先关闭原始响应体,避免连接池资源泄漏
        response.body().close();
        
        // 2. 处理响应体类型:如果要保留原始响应的contentType,先clone响应再获取
        // (clone的响应体是独立的流,不会消耗原始响应)
        Response clonedResponse = response.clone();
        MediaType contentType = clonedResponse.body().contentType();
        clonedResponse.body().close();
        
        // 3. 如果原始响应没有指定contentType,也可以手动指定(比如application/json)
        // MediaType contentType = MediaType.parse("application/json");
        
        // 4. 构建自定义的401响应体
        String customJson = CommonFunctions.getUnAuthorizedJson(context).toString();
        ResponseBody customBody = ResponseBody.create(contentType, customJson);
        
        // 5. 构建新的响应,保留原始响应的其他属性(headers、状态码等)
        return response.newBuilder()
                .body(customBody)
                .build();
    } else {
        // 非401响应直接返回
        return response;
    }
}

额外要注意的几个点:

  • Interceptor的注册方式:确保你把这个Interceptor添加到OkHttpClient的构建器中,用addInterceptor()(应用层拦截器)而不是addNetworkInterceptor()(网络层拦截器),因为应用层拦截器只会处理一次请求,更适合处理业务逻辑的401:
    OkHttpClient okHttpClient = new OkHttpClient.Builder()
            .addInterceptor(new YourAuthInterceptor(context)) // 这里添加你的拦截器
            .build();
    
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("你的基础URL")
            .client(okHttpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    
  • 回调中读取响应体:在enqueue的回调里,确保你正确读取响应体(比如用response.body().string()或者通过Converter解析成实体类),不要直接持有原始的ResponseBody对象,因为它还是一次性的。

内容的提问来源于stack exchange,提问作者emre akkaya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:22:36