okhttp使用post出现:RFC 7230 and RFC 3986错误

项目使用okhttp请求第三方接口不成功,对方服务器出现RFC 7230 and RFC 3986错误,原因如下

Tomcat在 7.0.73, 8.0.39, 8.5.7 版本后,添加了对于http头的验证。具体来说,就是添加了些规则去限制HTTP头的规范性

org.apache.tomcat.util.http.parser.HttpParser#IS_NOT_REQUEST_TARGET[]中定义了一堆not request target

if(IS_CONTROL[i] || i > 127 || i == 32 || i == 34 || i == 35 || i == 60 || i == 62 || i == 92 || i == 94 || i == 96 || i == 123 || i == 124 || i == 125) {
    IS_NOT_REQUEST_TARGET[i] = true;
}

转换过来就是以下字符(对应10进制ASCII看):

- 键盘上那些控制键:(<32或者=127)
- 非英文字符(>127)
- 空格(32)
- 双引号(34)
- #(35)
- <(60)
- >(62)
- 反斜杠(92)
- ^(94)
- TAB上面那个键,我也不晓得嫩个读(96)
- {(123)
- }(124)
- |(125)

项目代码

@POST("apis/notice/sendNotice")
Call<SpNoticeResult> sendSpNotice(@Query("content") String content,
                                  @Query("title") String title);

结合上边分析,原因就是发送post请求时,参数被拼接到url中,包含特殊字符导致.所以,把请求参数放在请求体里发送就好了!


修改如下:

  1. @Query改成@Field

  2. 添加@FormUrlEncoded注解,否则会报错@Field parameters can only be used with form encoding

@POST("apis/notice/sendNotice")
@FormUrlEncoded
Call<SpNoticeResult> sendSpNotice(@Field("content") String content,
                                  @Field("title") String title);

本人对okhttp并不是太熟悉,但是老项目在用,为了解决这个bug也是费了好大事,差点重写代码(哈哈...草率了)

看到下面这张图才豁然开朗,找到最优的解决方案

参考:

原文地址:https://www.cnblogs.com/linyufeng/p/13494588.html