欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在Golang中正確的修改HTTPRequest的Host的操作方法

 更新時(shí)間:2023年12月31日 08:33:09   作者:Kearth  
我們工作中經(jīng)常需要通過HTTP請(qǐng)求Server的服務(wù),比如腳本批量請(qǐng)求接口跑數(shù)據(jù),由于一些網(wǎng)關(guān)策略,部分Server會(huì)要求請(qǐng)求中Header里面附帶Host參數(shù),所以本文給大家介紹了如何在Golang中正確的修改HTTPRequest的Host,需要的朋友可以參考下

背景

我們工作中經(jīng)常需要通過HTTP請(qǐng)求Server的服務(wù),比如腳本批量請(qǐng)求接口跑數(shù)據(jù)。在這個(gè)過程中,由于一些網(wǎng)關(guān)策略,部分Server會(huì)要求請(qǐng)求中Header里面附帶Host參數(shù)。這時(shí),我們可能會(huì)想到在Header里面直接賦值Host,比如這樣:

req.Header.Add("Host", "www.example.com")
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

但請(qǐng)求的過程中會(huì)發(fā)現(xiàn)明明設(shè)置了,接收方卻收不到這個(gè)Host。因此下面我會(huì)闡述為什么會(huì)這樣,以及如何正確的修改HTTPRequest的Host。

為什么會(huì)這樣

首先我們打印一下Header.Add后的參數(shù)看看會(huì)怎樣

map[Host:[www.example.com]]

再排除世界上有鬼的情況下,我們可以合理分析出: Header.Add環(huán)節(jié)既然成功了,那么Host一定是在實(shí)際請(qǐng)求HTTP前被替換了

由于下一段代碼就是client.Do,因此有理由懷疑這個(gè)操作在Do方法里面

// 發(fā)送請(qǐng)求并獲取響應(yīng)
resp, err := client.Do(req)
if err != nil {
	fmt.Println("發(fā)送請(qǐng)求失敗:", err)
	return
}

追蹤下去,可以看到net/http包的源碼如下:

func (c *Client) Do(req *Request) (*Response, error) {
	return c.do(req)
}
func (c *Client) do(req *Request) (retres *Response, reterr error) {
    ... ... // 省略
    host := ""
	if req.Host != "" && req.Host != req.URL.Host {
		// If the caller specified a custom Host header and the
		// redirect location is relative, preserve the Host header
		// through the redirect. See issue #22233.
		if u, _ := url.Parse(loc); u != nil && !u.IsAbs() {
			host = req.Host
		}
	}
	ireq := reqs[0]
	req = &Request{
		Method:   redirectMethod,
		Response: resp,
		URL:      u,
		Header:   make(Header),
		Host:     host,
		Cancel:   ireq.Cancel,
		ctx:      ireq.ctx,
	}
    ... ... // 省略
}

這段指明:請(qǐng)求實(shí)際使用的Host默認(rèn)為空。如果req.Host字段不為空,且不與URL的Host相同,會(huì)使用req.Host

// If the caller specified a custom Host header and the redirect location is relative, preserve the Host header through the redirect.
// 如果調(diào)用者指定了自定義的 Host 標(biāo)頭并且重定向位置是相對(duì)路徑的話,通過重定向保留該 Host 標(biāo)頭。

那么我們來看看req.Host字段是什么

	// For server requests, Host specifies the host on which the
	// URL is sought. For HTTP/1 (per RFC 7230, section 5.4), this
	// is either the value of the "Host" header or the host name
	// given in the URL itself. For HTTP/2, it is the value of the
	// ":authority" pseudo-header field.
	// It may be of the form "host:port". For international domain
	// names, Host may be in Punycode or Unicode form. Use
	// golang.org/x/net/idna to convert it to either format if
	// needed.
	// To prevent DNS rebinding attacks, server Handlers should
	// validate that the Host header has a value for which the
	// Handler considers itself authoritative. The included
	// ServeMux supports patterns registered to particular host
	// names and thus protects its registered Handlers.
	//
	// For client requests, Host optionally overrides the Host
	// header to send. If empty, the Request.Write method uses
	// the value of URL.Host. Host may contain an international
	// domain name.
	Host string

這段注釋主要解釋了在 Go 語言中如何處理請(qǐng)求的 Host 標(biāo)頭。在服務(wù)器請(qǐng)求中,Host 指定要查找 URL 的主機(jī),可能是 Host 標(biāo)頭的值或 URL 本身中給定的主機(jī)名。對(duì)于客戶端請(qǐng)求,Host 可以選擇性地覆蓋要發(fā)送的 Host 標(biāo)頭,如果為空,則使用 URL.Host 的值。此外,還提到了國際化域名的處理和防止 DNS 重新綁定攻擊的注意事項(xiàng)。

這基本跟我們上文的結(jié)論相互印證了,至此我們搞清楚了為什么Header里面的Host不生效:因?yàn)镈o使用HTTP Request里面的Host字段,且不是Header里面的Host鍵對(duì)應(yīng)值

怎么解決

顯然,指明 req.Host 是一個(gè)較好的方案

req.Host = "www.example.com"

至此我們解決了這個(gè)問題

我們還能知道些什么

關(guān)于 issue #22233

if req.Host != "" && req.Host != req.URL.Host {
    // If the caller specified a custom Host header and the
    // redirect location is relative, preserve the Host header
    // through the redirect. See issue #22233.
    if u, _ := url.Parse(loc); u != nil && !u.IsAbs() {
        host = req.Host
    }
}

我們注意到在這段代碼中,提到了issue #22233,那么它到底是什么呢,我們一起來看看!

這個(gè)問題 #issue 22233 是2017年由 timonwong 提出的,當(dāng)時(shí)版本是 go1.9.1 darwin/amd64。問題內(nèi)容是:客戶端跟隨重定向時(shí)不會(huì)保留 Host 標(biāo)頭 golang的一位維護(hù)者tombergan 響應(yīng)了這個(gè)問題: 認(rèn)為這絕對(duì)是個(gè)bug

但同時(shí)他也提出重定向時(shí)復(fù)制哪些header內(nèi)容是沒有一個(gè)較好的確切的指導(dǎo)的。

Parent:     645c661a (cmd/compile/internal/syntax: factor out list parsing)
Author:     Tom Bergan <tombergan@google.com>
AuthorDate: 2017-10-13 15:56:37 -0700
Commit:     Tom Bergan <tombergan@google.com>
CommitDate: 2017-10-16 17:44:26 +0000
net/http: preserve Host header following a relative redirect
If the client sends a request with a custom Host header and receives
a relative redirect in response, the second request should use the
same Host header as the first request. However, if the response is
an abolute redirect, the Host header should not be preserved. See
further discussion on the issue tracker.
Fixes #22233
Change-Id: I8796e2fbc1c89b3445e651f739d5d0c82e727c14
Reviewed-on: https://go-review.googlesource.com/70792
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Run-TryBot: Joe Tsai <thebrokentoaster@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

最終于2017-10-16這次提交中他修復(fù)了這個(gè)問題,從郵箱看這位大神應(yīng)該是google的一位員工。代碼改動(dòng)如下:

至此我們了解了有關(guān)于 issue #22233 的全部

關(guān)于 Host 是什么

在前文中,Request的Host屬性的注釋中提到: Host指定了正在尋找的主機(jī)。

    // For server requests, Host specifies the host on which the
    // URL is sought. For HTTP/1 (per RFC 7230, section 5.4), this
    // is either the value of the "Host" header or the host name
    // given in the URL itself. For HTTP/2, it is the value of the
    // ":authority" pseudo-header field.

從這里面提到的 RFC 7230,section 5.4 可以看到

① Host提供目標(biāo)URI的主機(jī)、端口信息,使服務(wù)器在單個(gè)IP地址上可以根據(jù)不同的主機(jī)名提供不同的服務(wù)和資源。(比如單機(jī)部署多個(gè)網(wǎng)站

② HTTP/1.1必須發(fā)送Host字段。當(dāng)代理服務(wù)接受到absolute-form形式的請(qǐng)求時(shí),忽略Host字段,取請(qǐng)求中的主機(jī)信息。轉(zhuǎn)發(fā)請(qǐng)求的時(shí)候需要基于接收的請(qǐng)求重新生成Host,而不是轉(zhuǎn)發(fā)接受到的Host。(URL里面的主機(jī)信息優(yōu)先級(jí)高于Host字段。轉(zhuǎn)發(fā)請(qǐng)求的時(shí)候Host字段不透傳

③ Host本身可以任意修改,因此如果依賴Host字段進(jìn)行代理轉(zhuǎn)發(fā)、緩存密鑰、身份驗(yàn)證等,需要先行校驗(yàn)Host值的合法性,避免Host頭攻擊

④ 對(duì)于缺少或者有多個(gè)Host字段的HTTP/1.1請(qǐng)求消息,服務(wù)器需要返回400 Bad Request 狀態(tài)碼 (Host字段有且只能有一個(gè)

至此,我們弄明白了Host是什么

// example: www.example.org or www.example.org:8080
Host = uri-host [":" port]; 

以上就是在Golang中正確的修改HTTPRequest的Host的操作方法的詳細(xì)內(nèi)容,更多關(guān)于Golang修改HTTPRequest的Host的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang語言實(shí)現(xiàn)gRPC的具體使用

    Golang語言實(shí)現(xiàn)gRPC的具體使用

    本文主要介紹了Golang語言實(shí)現(xiàn)gRPC的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • golang中一種不常見的switch語句寫法示例詳解

    golang中一種不常見的switch語句寫法示例詳解

    這篇文章主要介紹了golang中一種不常見的switch語句寫法,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-05-05
  • Golang利用casbin實(shí)現(xiàn)權(quán)限驗(yàn)證詳解

    Golang利用casbin實(shí)現(xiàn)權(quán)限驗(yàn)證詳解

    Casbin是一個(gè)強(qiáng)大的、高效的開源訪問控制框架,其權(quán)限管理機(jī)制支持多種訪問控制模型,Casbin只負(fù)責(zé)訪問控制。本文將利用casbin實(shí)現(xiàn)權(quán)限驗(yàn)證功能,需要的可以參考一下
    2023-02-02
  • Go1.21新增maps包的用法詳解

    Go1.21新增maps包的用法詳解

    maps?包提供了幾個(gè)非常有用的用于操作?map?類型(任何類型的?map)的函數(shù),本文為大家整理了部分函數(shù)的具體用法,感興趣的小伙伴可以了解一下
    2023-08-08
  • Golang使用ReverseProxy實(shí)現(xiàn)反向代理的方法

    Golang使用ReverseProxy實(shí)現(xiàn)反向代理的方法

    本文介紹了如何使用Golang的ReverseProxy實(shí)現(xiàn)反向代理,包括源碼結(jié)構(gòu)解析和官方單機(jī)示例NewSingleHostReverseProxy,同時(shí)指出,若要實(shí)現(xiàn)負(fù)載均衡,需要自行開發(fā),還提供了一個(gè)簡單的HTTP服務(wù)用于測(cè)試,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • golang validator參數(shù)校驗(yàn)的實(shí)現(xiàn)

    golang validator參數(shù)校驗(yàn)的實(shí)現(xiàn)

    這篇文章主要介紹了golang validator參數(shù)校驗(yàn)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • 詳解go語言中并發(fā)安全和鎖問題

    詳解go語言中并發(fā)安全和鎖問題

    這篇文章主要介紹了go語言中并發(fā)安全和鎖問題,包含互斥鎖解鎖過程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-10-10
  • 特殊字符的json序列化總結(jié)大全

    特殊字符的json序列化總結(jié)大全

    這篇文章主要給大家介紹了關(guān)于特殊字符的json序列化的相關(guān)資料,通過示例代碼分別給大家介紹了關(guān)于python 、 rust 、 java 和golang對(duì)特殊字符的json序列化操作,需要的朋友可以參考借鑒,下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • golang 獲取字符串長度的案例

    golang 獲取字符串長度的案例

    這篇文章主要介紹了golang 獲取字符串長度的案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go map發(fā)生內(nèi)存泄漏解決方法

    Go map發(fā)生內(nèi)存泄漏解決方法

    這篇文章主要介紹了Go map發(fā)生內(nèi)存泄漏解決方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11

最新評(píng)論