對(duì)源碼有一定的了解拍顷,以為基本可以駕馭了,誰(shuí)知道塘幅,坑來(lái)了昔案。
問(wèn)題描述:
上線接口的某一天,有用戶報(bào)障电媳,說(shuō)登錄不上踏揣,而且陸續(xù)有報(bào)障。
通過(guò)log 發(fā)現(xiàn)登錄不上匾乓,都有一個(gè)類(lèi)似的報(bào)錯(cuò):
“java.lang.IllegalArgumentException: Unexpected char 0x514d at 4 in wifiSsid value: "360免費(fèi)WiFi-DP" at ”
什么捞稿?怎么和wifiSsid有關(guān)系了?后來(lái)查了一下代碼拼缝,發(fā)現(xiàn)確實(shí)在登錄接口上通過(guò)請(qǐng)求頭的形式上傳了 wifissid, 也就是連接的wifi的名字娱局。Exception描述是第四個(gè) char ,也就是“免”字咧七?難道是因?yàn)橹形牡脑蛩テ耄慨?dāng)時(shí)是這么猜測(cè)的。
源碼查詢
猜測(cè)并不能作為判斷的標(biāo)準(zhǔn)继阻,然后做了一下測(cè)試娇斩,果然連接含義中文名字的wifi就有問(wèn)題仁卷,也就是不能添加中文到請(qǐng)求頭里面。這是為什么呢犬第?最后還是通過(guò)源碼進(jìn)行的求證:
在okhttp的源碼Header.java锦积,發(fā)現(xiàn)set 和add header, 都會(huì)有這個(gè)判斷:
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歉嗓,果然是這樣丰介,踩到深坑了。無(wú)論是header的 Key 和Value都是不能含有中文的鉴分,一旦判定為有中文的出現(xiàn)哮幢,就會(huì)拋出異常,中斷請(qǐng)求志珍。
后面想了一下橙垢,以前使用okhttp2的時(shí)候,也有上傳相同的請(qǐng)求頭伦糯,為什么就沒(méi)有這個(gè)問(wèn)題呢柜某?也同樣去查看了一下okhttp2的源碼,發(fā)現(xiàn)這個(gè)判斷是okhttp3才有的敛纲,okhttp2其實(shí)并沒(méi)有這個(gè)判斷喂击。
解決方案:
解決方案有以下幾種:
- 不要傳了(當(dāng)然這個(gè)不符合需求)
- 把源碼這個(gè)地方改了(也不是太好,不知道會(huì)不會(huì)引起其他問(wèn)題)
- 把中文 encode以下(相對(duì)較好的辦法):
ssid = URLEncoder.encode(ssid);
總結(jié)
遇到問(wèn)題不可怕淤翔,主要是要做好分析翰绊,及時(shí)解決,多做總結(jié)旁壮,避免后門(mén)再次踩同樣的坑监嗜。