1. 程式人生 > 實用技巧 >okhttp使用post出現:RFC 7230 and RFC 3986錯誤

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也是費了好大事,差點重寫程式碼(哈哈...草率了)

看到下面這張圖才豁然開朗,找到最優的解決方案

參考: