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也是费了好大事,差点重写代码(哈哈...草率了)

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

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

参考:

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

上一篇:kubernetes之十一: Secret 使用


下一篇:基础类库积累--HTTP操作类