在 Go 代碼中如何綁定 Host?
在公司內(nèi)部,為了安全,可能會(huì)有域名是需要綁定 host 才能訪問的,如果是通過瀏覽器訪問,我們會(huì)修改本機(jī)的 hosts 文件;然而,如果是要通過程序訪問這樣的域名,我們是否依然必須綁定 host 呢?答案當(dāng)然是否定的,而且,依賴本地綁定的 host,程序到其他機(jī)器部署,也必須在那臺(tái)機(jī)器綁定 host,如果機(jī)器很多呢?
剛好前兩天,群里也有人問類似的問題
本文示例:
- IP:192.168.1.102,也就是說(shuō)需要訪問這臺(tái)機(jī)器上的資源
- 域名:studygolang.com,nginx 配置的虛擬主機(jī)
- url path:/testhost.txt,內(nèi)容是:Welcome to studygolang.com
需求:需要請(qǐng)求服務(wù)器上的 testhost.txt 資源。
1、Linux Shell 的解決方案
Linux 下的 curl 程序可以綁定 host,因此,在 shell 中可以很簡(jiǎn)單的實(shí)現(xiàn),如:curl -H "Host:studygolang.com" http://192.168.1.102/testhost.txt。
2、PHP 的解決方案
1)通過 curl 擴(kuò)展實(shí)現(xiàn)
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_HTTPHEADER, array('Host:studygolang.com'));
- curl_setopt($ch, CURLOPT_URL, 'http://192.168.1.102/testhost.txt');
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
- $ret = curl_exec($ch);
- var_dump($ret);
2)不依賴 curl 擴(kuò)展的方式
- // Create a stream
- $opts = array(
- 'http'=>array(
- 'method'=>"GET",
- 'header'=>"Host:studygolang.com"
- )
- );
- $context = stream_context_create($opts);
- // Open the file using the HTTP headers set above
- $ret = file_get_contents('http://192.168.1.102/testhost.txt', false, $context);
- var_dump($ret);
3、Golang 的解決方案
由于 Go 標(biāo)準(zhǔn)庫(kù)實(shí)現(xiàn)了 http 協(xié)議,在 net/http 包中尋找解決方案。
一般的,請(qǐng)求一個(gè) url,我們通過以下代碼實(shí)現(xiàn):
- http.Get(url)
然而,針對(duì)本文說(shuō)到的這種情況,無(wú)論 url = "http://192.168.1.102/testhost.txt" 還是 url = "http://studygolang.com/testhost.txt",都無(wú)法請(qǐng)求到資源(沒有綁定 host 的情況)。
在 http 包中的 Request 結(jié)構(gòu)中,有一個(gè)字段:Host,我們可以參考上面兩種解決方案,設(shè)置 Host 的值。方法如下:
- package main
- import (
- "net/http"
- "io/ioutil"
- "fmt"
- )
- func main() {
- req, err := http.NewRequest("GET", "http://192.168.1.102/testhost.txt", nil)
- if err != nil {
- panic(err)
- }
- req.Host = "studygolang.com"
- resp, err := http.DefaultClient.Do(req)
- if err != nil {
- panic(err)
- }
- defer resp.Body.Close()
- body, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- panic(err)
- }
- fmt.Println(string(body))
- }
4、總結(jié)
不管是什么方式、什么語(yǔ)言,歸根結(jié)底,需要告知服務(wù)器請(qǐng)求的是哪個(gè) Host,這個(gè)是 HTTP 協(xié)議的 Host 頭。如果不手動(dòng)設(shè)置 Host 頭,則會(huì)從請(qǐng)求的 url 中獲取。