为何支持请求体的OkHttp POST请求缺失Content-Type请求头?
解决全局统一处理Content-Type请求头的问题
看起来你在Retrofit项目中遇到了Content-Type头自动处理不符合预期的情况,同时希望用全局拦截器替代逐个接口加注解的方案,我来给你梳理下可行的解决方案:
核心问题分析
你提到“不支持请求体的请求方法会被移除Content-Type头,但实际情况并非如此”,这大概率是因为Retrofit的默认逻辑被自定义拦截器、转换器或者特殊请求配置(比如GET方法带@Body注解)干扰了。既然你已经确认User-Agent头设置正常,说明全局拦截器的配置路径是通的,我们可以通过自定义Interceptor来完全掌控Content-Type的处理逻辑。
全局Interceptor实现方案
下面是一步到位的代码实现,能帮你统一处理所有请求的Content-Type头:
1. 编写自定义Content-Type拦截器
class ContentTypeInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() var modifiedRequest = originalRequest // 根据HTTP方法类型,精准控制Content-Type头 when (originalRequest.method.uppercase()) { // 对不支持请求体的HTTP方法,强制移除Content-Type "GET", "HEAD", "DELETE", "OPTIONS", "TRACE", "CONNECT" -> { modifiedRequest = originalRequest.newBuilder() .removeHeader("Content-Type") .build() } // 对支持请求体的方法,自动补充默认Content-Type(如果未设置) "POST", "PUT", "PATCH" -> { if (originalRequest.headers("Content-Type").isEmpty()) { modifiedRequest = originalRequest.newBuilder() .addHeader("Content-Type", "application/json; charset=utf-8") .build() } } } return chain.proceed(modifiedRequest) } }
2. 将拦截器绑定到OkHttpClient
val okHttpClient = OkHttpClient.Builder() .addInterceptor(ContentTypeInterceptor()) // 这里可以添加其他拦截器(比如日志、认证)或配置超时参数 .build()
3. 把配置好的OkHttpClient传给Retrofit
val retrofit = Retrofit.Builder() .baseUrl("你的API基础地址") .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build() val api = retrofit.create(Api::class.java)
额外说明
- 优先级处理:如果某个特殊接口需要自定义Content-Type,直接在接口方法上添加
@Headers("Content-Type: multipart/form-data")即可——Retrofit会优先使用方法级别的注解配置,不会被全局拦截器覆盖。 - 异常场景排查:如果之前的自动移除逻辑失效,可能是你项目中的GsonConverter或者其他拦截器提前给请求加上了Content-Type头,导致Retrofit的默认清理逻辑没触发,用这个自定义拦截器可以强制覆盖处理。
内容的提问来源于stack exchange,提问作者es0329
相关产品推荐
相关产品推荐

