前言##
筆者最近時間一直在學習和寫Ruby和Go,尤其是Go,作為雲計算時代的標准語言,寫起來還是相當有感覺的,難過其會越來越火。
不過寫的過程中,也遇到了一些小問題,本文就是分享關於go語言設置 HTTP請求當中 Host Header的一個小注意事項。
常規做法##
通常我們在設置HTTP的Header請求時,一般都是這么做:
Header.Add("Authentization", "TOKEN")
Header.Add("Content-Type", "application/json")
...
Java, Ruby, Go 都是如此,區別的只是語法不同。但是對於Host Header的處理就不同了。在Go中,如果我們這么寫:
header.Add("Host", "XXXXXXXXX")
那么問題就出來了 —— 也許從請求發送的log中,你看不到任何的錯誤,但是如果查看服務端的log,你會發現,服務端接受到Host Header並不是你想發送的,而仍然是URL中的Host。
這是為什么呢?
為什么Go中Host Header不能這么加?##
原來Go的設計上是用一個單獨的HOST屬性來定義此Request屬性,參考net/http包中Request.go文件定義的Request結構體:
// For server requests Host specifies the host on which the
// URL is sought. Per RFC 2616, this is either the value of
// the "Host" header or the host name given in the URL itself.
// It may be of the form "host:port".
//
// For client requests Host optionally overrides the Host
// header to send. If empty, the Request.Write method uses
// the value of URL.Host.
Host string
那么在使用上,如果我們想傳一個特定的Host,應該這么做:
Req.Host="XXXX"
但是,為啥Go就如此特殊呢?
Go為啥如此特殊?##
原來從HTTP Spec角度,是不大希望讓Host Header可以修改,這里的HOST應該是從URL得到,而不是任意的指定。
但是考慮到很多場景,尤其是Client Requests,很多時候我們希望能夠修改這個HOST參數,來模擬我們的需求,如果Go能響應修改其源碼就好了?
搜一下,發現這個問題也確實有人提過,如下:
[net/http: Setting custom "Host" request header doesn't have effect #7682](net/http: Setting custom "Host" request header doesn't have effect #7682)
而結論是:
I don't think we can safely change the behavior at this point.
最好也只是更新了文檔,去掉了關於HOST參數的歧義。
對Go實現的第三方工具的影響##
既然go語言沒有更改這個需求,為了適應大家的習慣,如果有必要,我們可以這樣做一個Workaround:
if host := header.Get("Host"); host != "" {
req.Host = host
}
而且這也是很多用Go寫的工具的通用做法,比如:
Contact me ?
Email: jinsdu@outlook.com
Blog: http://www.cnblogs.com/jinsdu/
Github: https://github.com/CarlJi
童鞋,如果覺得本文還算用心,還算有用,何不點個贊呢(⊙o⊙)?