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
相关产品推荐
相关产品推荐

