Retrofit拦截器无法获取请求头,@FormUrlEncoded头也缺失?
问题原因与解决方案
你看不到@FormUrlEncoded对应的请求头,核心原因是OkHttp拦截器的执行顺序:
你当前用的是addInterceptor添加应用拦截器,它的执行时机在OkHttp的桥接拦截器(BridgeInterceptor)之前。而@FormUrlEncoded对应的Content-Type: application/x-www-form-urlencoded; charset=UTF-8请求头,是由桥接拦截器根据请求体的MediaType自动添加的——在应用拦截器阶段,这个头还没被注入到请求中,所以你打印headers会看不到,调用toMultimap()自然也是空集合。
两种解决办法
1. 改用网络拦截器
将拦截器添加方式从addInterceptor换成addNetworkInterceptor,这样拦截器会在桥接拦截器之后执行,就能拿到完整的请求头:
OkHttpClient.Builder() .cookieJar(SessionCookieJar()) // 替换成addNetworkInterceptor .addNetworkInterceptor { chain -> chain.request().also { request -> val buffer = Buffer().also { request.body()?.writeTo(it) } Log.d(TAG, "Intercepted request:") Log.d(TAG, request.headers().toString()) Log.d(TAG, buffer.readUtf8()) }.let(chain::proceed) } .build()
2. 在应用拦截器中直接读取请求体的MediaType
如果必须保留应用拦截器,可以直接从请求体中获取对应的MediaType(这就是后续会被转换成请求头的内容):
.addInterceptor { chain -> chain.request().also { request -> val buffer = Buffer().also { request.body()?.writeTo(it) } Log.d(TAG, "Intercepted request:") // 直接打印请求体的MediaType request.body()?.contentType()?.let { Log.d(TAG, "Content-Type (from body): $it") } Log.d(TAG, buffer.readUtf8()) }.let(chain::proceed) }
需要明确的是:@FormUrlEncoded注解的作用是让Retrofit生成带有正确MediaType的FormBody,而不是直接添加请求头——请求头的添加是OkHttp桥接拦截器的职责,这就是你在当前拦截器中看不到它的原因。
内容的提问来源于stack exchange,提问作者askSoap
相关产品推荐
相关产品推荐

