路徑中的斜杠
我們常見的網址如 http://www.cnblogs.com/aaa/bbb/1.html 是由多級的結構(目錄/文件夾)組成的,這里關注的是其中的aaa和bbb,它們之間用斜杠(/)分隔。從最大自由度來講,每一級結構的名字是可以隨意取的。既然名字可以隨意取,而且上下級之間是用/來做分隔,那么如果名字里面有斜杠要怎么辦呢?可能有人說Windows不允許啊,在Windows文件夾或者文件的名字里面不能出現斜杠,在web是允許的。由於斜杠在網址中代表上下級結構的分隔符,所以如果某一層的文件夾出現斜杠的話,必須進行轉碼。具體的這個斜杠就得轉成%2F,即是百分號后加2位十六進制表示的ASCII碼。所以%2F代表文件夾名字中的斜杠,不代表上下級文件夾的分隔。
Unirest是什么?
現在軟件web化非常流行,而且多數是前后端分離,所以web API通常是給前端調的。但也存在一種可能,就是我們自己寫一個軟件需要去訪問(調用)別人的web API。此時就需要一些組件封裝了HTTP協議,然后我們就可以方便地使用。這樣的組件很多,但是由於HTTP協議比較復雜,所以實現這樣的組件要做到強大+易用,還真的不太容易。在眾多HTTP組件之中,Unirest就是難得的封裝得非常好用的一套組件。
歷險過程
前段時間我寫一個程序需要去訪問其他系統的web接口,網址大概長這樣:http://www.abc.com/one%2Ftwo/abc,調用接口的結果是下載一個文件。一開始用了其他的組件,但下載的文件內容中的中文是亂碼,且文件不完整。由於我對那套組件不熟,所以我就想到換為我比較熟的unirest。於是去 https://mvnrepository.com/ 找了unirest的引用代碼,結果發現還不止一個。我也忘了以前是怎么選擇的,所以就習慣性地采用那個排名第一的,也就是下載量最大的那個。估計以前也是用那個,以前也沒遇到什么問題。三下五除二,說干就干,輕車熟路,一番噼里啪啦,很快弄好了。
啟動機器調試。什么?404(找不到文件資源)?我沒看錯吧?各種檢查,沒有發現原因。把代碼中的網址復制到瀏覽器,結果401(未登錄)。因為我沒有傳送認證參數,401就是對的。我多么想代碼也能得到401,可他卻就是404!但是404是個很不好解決的問題。我知道,資源就在那里,誰知道哪個地方寫錯了呢。服務器就告訴你“找不到。至於哪里寫錯了,不知道,你猜”。我進行了各種嘗試,也包括把%2F變直接變成斜杠去訪問服務器,給的回答是。項目不存在,狀態碼是200。事情陷入了僵局。
經同事提醒,使用了抓包工具。原來unirest真的“幫我”把%2F轉成斜杠了!好吧,既然你會幫我一次解碼,那我就編碼兩次,讓你解一次結果就剛好是對的。編解碼我還是懂的。查了一下%的編碼是%25,於是我把網址變成這樣http://www.abc.com/one%252Ftwo/abc。程序運行,又是404!從抓包工具來看,……,這次他就干脆不解碼了,你說氣不氣人?整個人又陷入了絕望。我那么信賴的unirest,怎么會出現這樣的bug?
接下來怎么辦?我還能有其他的選擇嗎?第一,其他的組件我也不熟,出了問題更是難排查。第2,Unirest基本是業界最好的了,他都搞不定,其他組件會更好嗎。
后來又經過各種排查,排查到了unirest的源頭,我又再次去了 https://mvnrepository.com/。看到了這一幕
這個時候我才發現,原來我使用的已經有好幾年不更新了,而那個一直有更新的下載量並不是第一。總算又看到了一線希望,馬上下載來試這一次,問題解決了!!!他不會自動把網址中的%2F進行轉碼!
教訓啊
- 使用unirest要留意你使用的是哪個unirest。
- 當遇到一些技術問題,走投無路的時候,可以在各個分叉點進行嘗試。所以呢,在研發或選型的過程中就要記錄這些分叉點。典型的就是有多種選擇的時候。
現在復盤寫出來思路很清晰,但是人在事中時,是帶着混亂的。往往到了山窮水盡疑無路,而不知道哪里有柳暗花明又一村。