OkHttp3+Retrofit2中Content-Type请求头莫名被移除问题排查
问题:OkHttp/Retrofit中自定义Content-Type请求头被莫名移除
我使用OkHttp3和Retrofit2发送请求,自定义拦截器添加请求头的代码如下:
override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request().newBuilder() .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") .addHeader("Content-Type2", "*") .addHeader("3Content-Type2", "*") .addHeader("Host", "blabla.com") .build() return chain.proceed(request) }
OkHttp客户端配置了ChuckerInterceptor和HttpLoggingInterceptor,但出现以下异常情况:
- HttpLoggingInterceptor中能看到设置的Content-Type头
- ChuckerInterceptor里看不到该头,且返回结果和缺少此头的请求一致(Content-Type2、3Content-Type2头正常显示)
Postman测试对比:
- 携带Content-Type头时,返回预期的短文本
- 不携带时,返回与OkHttp客户端一致的HTML代码
客户端完整配置代码:
val logging = HttpLoggingInterceptor() logging.level = (HttpLoggingInterceptor.Level.BODY) val cookieManager = CookieManager() val chuckerCollector = ChuckerCollector( context = MainActivity.context, showNotification = true, retentionPeriod = RetentionManager.Period.ONE_HOUR ) val chuckerInterceptor = ChuckerInterceptor.Builder(MainActivity.context) .collector(chuckerCollector) .maxContentLength(250_000L) .redactHeaders("Auth-Token", "Bearer") .alwaysReadResponseBody(true) .build() cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL) val client: OkHttpClient = OkHttpClient .Builder() .addInterceptor(HeadersInterceptor()) .addInterceptor(chuckerInterceptor) .build() val retrofit = Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(ScalarsConverterFactory.create()) .client(client) .build() interface = retrofit.create(interface::class.java)
我尝试添加网络拦截器修复,依然无效:
.addNetworkInterceptor(Interceptor { chain -> val originalRequest = chain.request() val modifiedRequest = originalRequest.newBuilder() .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") .build() chain.proceed(modifiedRequest) })
可能原因及解决方案
1. OkHttp自动重写Content-Type头
OkHttp会根据请求体类型自动设置/覆盖Content-Type头:
- 如果是无请求体的GET请求,服务器强制要求带该头时,用
header()替代addHeader()强制覆盖 - 如果是POST请求,先确认请求体是否为
application/x-www-form-urlencoded格式(比如用FormBody构建),此时OkHttp会自动设置正确的Content-Type,无需手动添加;若必须手动指定,用header()替换addHeader()确保覆盖默认值
2. 拦截器执行顺序冲突
当前拦截器顺序为「自定义HeadersInterceptor → ChuckerInterceptor」,若后续有逻辑(包括OkHttp内部逻辑)修改请求头,会覆盖你的设置:
- 确保自定义拦截器是最后添加的应用拦截器,避免被其他逻辑修改
- 检查Retrofit的Converter是否存在隐式修改请求头的行为
3. 抓包验证实际请求头
用Charles、Fiddler等抓包工具直接抓取OkHttp发送的请求,确认Content-Type头是否真的被发送——这是最直接的验证方式,能排除日志工具的显示问题
4. 手动Host头的干扰
OkHttp会自动处理Host头,手动设置可能引发内部逻辑冲突,间接影响其他头的处理:尝试移除代码中手动添加的Host头,再测试Content-Type是否正常发送
内容的提问来源于stack exchange,提问作者Questions100
相关产品推荐
相关产品推荐

