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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 23:33:25