這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
前言
筆者最近時間一直在學習和寫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寫的工具的通用做法,比如:
surf
vegeta
Contact me ?
Email: jinsdu@outlook.com
Blog: http://www.cnblogs.com/jinsdu/
Github: https://github.com/CarlJi
童鞋,如果覺得本文還算用心,還算有用,何不點個贊呢(⊙o⊙)?