okhttp3 請求頭不能爲中文的坑

對源碼有一定的瞭解,以爲基本可以駕馭了,誰知道,坑來了。(前段時間在簡書的記錄,轉移到CSDN來)

問題描述:

上線接口的某一天,有用戶報障,說登錄不上,而且陸續有報障。

通過log 發現登錄不上,都有一個類似的報錯:
“java.lang.IllegalArgumentException: Unexpected char 0x514d at 4 in wifiSsid value: “360免費WiFi-DP” at ”

什麼?怎麼和wifiSsid有關係了?後來查了一下代碼,發現確實在登錄接口上通過請求頭的形式上傳了 wifissid, 也就是連接的wifi的名字。Exception描述是第四個 char ,也就是“免”字?難道是因爲中文的原因?當時是這麼猜測的。

源碼查詢

猜測並不能作爲判斷的標準,然後做了一下測試,果然連接含義中文名字的wifi就有問題,也就是不能添加中文到請求頭裏面。這是爲什麼呢?最後還是通過源碼進行的求證:

在okhttp的源碼Header.java,發現set 和add header, 都會有這個判斷:

    private void checkNameAndValue(String name, String value) {
      if (name == null) throw new NullPointerException("name == null");
      if (name.isEmpty()) throw new IllegalArgumentException("name is empty");
      for (int i = 0, length = name.length(); i < length; i++) {
        char c = name.charAt(i);
        if (c <= '\u0020' || c >= '\u007f') {
          throw new IllegalArgumentException(Util.format(
              "Unexpected char %#04x at %d in header name: %s", (int) c, i, name));
        }
      }
      if (value == null) throw new NullPointerException("value == null");
      for (int i = 0, length = value.length(); i < length; i++) {
        char c = value.charAt(i);
        if ((c <= '\u001f' && c != '\t') || c >= '\u007f') {
          throw new IllegalArgumentException(Util.format(
              "Unexpected char %#04x at %d in %s value: %s", (int) c, i, name, value));
        }
      }
    }

嗷,No,果然是這樣,踩到深坑了。無論是header的 Key 和Value都是不能含有中文的,一旦判定爲有中文的出現,就會拋出異常,中斷請求。

後面想了一下,以前使用okhttp2的時候,也有上傳相同的請求頭,爲什麼就沒有這個問題呢?也同樣去查看了一下okhttp2的源碼,發現這個判斷是okhttp3纔有的,okhttp2其實並沒有這個判斷。

解決方案:

解決方案有以下幾種:

  1. 不要傳了(當然這個不符合需求)
  2. 把源碼這個地方改了(也不是太好,不知道會不會引起其他問題)
  3. 把中文 encode以下(相對較好的辦法):
    ssid = URLEncoder.encode(ssid);
總結

遇到問題不可怕,主要是要做好分析,及時解決,多做總結,避免後門再次踩同樣的坑。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章