哭暈!不懂搜索盲目造輪子:Golang打印請求體,大神2行搞定!

引言

在Golang與其他web服務(包括髮送和接收)的接口調試,一直是一個痛點。將所有的值都放入fmt也挺麻煩的。

故障排除時,傻瓜式地fmt.Printf(" %+v ", req),輸出內容慘不忍睹。

為了簡化操作,有必要寫個函數,隨處可用,於是有了下面的代碼。

哭暈!不懂搜索盲目造輪子:Golang打印請求體,大神2行搞定!

正文

直接上代碼:

<code>func formatRequest(r *http.Request) string {

 var request []string

 url := fmt.Sprintf(“%v %v %v”, r.Method, r.URL, r.Proto)
 request = append(request, url)

 request = append(request, fmt.Sprintf(“Host: %v”, r.Host))

 for name, headers := range r.Header {
   name = strings.ToLower(name)
   for _, h := range headers {
     request = append(request, fmt.Sprintf(“%v: %v”, name, h))
   }
 }
 
 // 處理POST請求體
 if r.Method == “POST” {
    r.ParseForm()
    request = append(request, “\n”)
    request = append(request, r.Form.Encode())
 } 

  return strings.Join(request, “\n”)
}/<code>

輸出結果看起來時這樣的

<code>POST https://blabla.example.com/o/oauth2/token HTTP/1.1
Host: blabla.example.com
content-type: application/x-www-form-urlencoded
client_id=ssssss&client_secret=sssss&grant_type=authorization_code&redirect_uri=ssssss&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile/<code>

一個小問題是,如果讀一個外部請求的 r.Body,只能去緩衝區。這意味著,請求有可能失敗,因為發送的 Content-Length 頭將設置為請求的原始長度。造成請求體的實際長度為0。

為了解決這個問題,可以把正文讀入緩衝區,然後打印出請求後再寫回來:

<code>// 緩存請求體
bodyBuffer, _ := ioutil.ReadAll(r.Body)
req.Body = myReader{bytes.NewBuffer(buf)}
fmt.Printf("--> %s\n\n", formatRequest(req))
req.Body = myReader{bytes.NewBuffer(buf)}/<code>


輪子已經好了

無可避免,還是搜索的不夠徹底,這個需求的輪子早就造好,放在golang裡了。

httputil包有一個預先準備好的DumpRequest方法。輸出幾乎完全一樣,這太讚的,因為它少了對第三方代碼的依賴。

結果就是2行搞定,還有2行是錯誤處理。

<code>requestDump, err := httputil.DumpRequest(req, true)
if err != nil {
  fmt.Println(err)
}
fmt.Println(string(requestDump))/<code>

req參數是http, true讓函數知道是否存在請求體。


寫在最後

大神都已經造好輪子了,我們只用找出來裝上用就行了。

Happy coding :)


分享到:


相關文章: