简体   繁体   English

golang`http.Request`的`Host`和`URL.Host`有什么区别?

[英]What is the difference between `Host` and `URL.Host` for golang `http.Request`?

When developing golang http application, I use http.Request a lot. 在开发golang http应用程序时,我http.Request使用http.Request When accessing request host address, I would use req.Host , but I find that there is req.URL.Host field, but when I print it, it's empty. 当访问请求主机地址时,我会使用req.Host ,但我发现有req.URL.Host字段,但是当我打印它时,它是空的。

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Println("uri Host: " + r.URL.Host + " Scheme: " + r.URL.Scheme)
    fmt.Println("Host: " + r.Host)
}

The documentation of http.Request gives the following comments, while net/url does not give much clue. http.Request的文档给出了以下注释,而net/url没有提供太多线索。

// 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 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.
//
// 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

It seems to me that there are two host value in a request: uri line and Host header, like: 在我看来,请求中有两个主机值:uri行和Host头,如:

GET http://localhost:8080/ HTTP/1.1
Host: localhost:8080

But it does not solve many problems than it creates: 但它并没有解决许多问题而不是它造成的问题:

  1. Why are there two different Host field in request? 为什么请求中有两个不同的Host字段? I mean isn't this a duplicate? 我的意思是这不是重复的吗?
  2. Can the two Host fields be different in the same request? 两个Host字段在同一个请求中是否可以不同?
  3. Which one should I use for what situation? 我应该在哪种情况下使用哪一个?

Answers with a real HTTP request example would be the best. 具有真实HTTP请求示例的答案将是最好的。 Thanks in advance. 提前致谢。

The r.URL field is created by parsing the HTTP request URI. r.URL字段是通过解析HTTP请求URI创建的。

The r.Host field is the value of the Host request header . r.Host字段是Host请求标头的值。 It's the same value as calling r.Header.Get("Host") . 它与调用r.Header.Get("Host")值相同。

If the HTTP request on the wire is: 如果线路上的HTTP请求是:

 GET /pub/WWW/TheProject.html HTTP/1.1
 Host: www.example.org:8080

then r.URL.Host is "" and r.Host is www.example.org:8080 . 然后r.URL.Host是“”而r.Hostwww.example.org:8080

The value of r.URL.Host and r.Host are almost always different. r.URL.Hostr.Host的值几乎总是不同的。 On a proxy server, r.URL.Host is the host of the target server and r.Host is the host of the proxy server itself. 在代理服务器上, r.URL.Host是目标服务器的主机, r.Host是代理服务器本身的主机。 When not connecting through a proxy, the client does not specify a host in the request URI. 未通过代理连接时,客户端不会在请求URI中指定主机。 In this scenario, r.URL.Host is the empty string. 在这种情况下, r.URL.Host是空字符串。

If you are not implementing a proxy, then you should use r.Host to determine the host. 如果您没有实现代理,那么您应该使用r.Host来确定主机。

Essentially http.Request.Host is for convenience. 基本上http.Request.Host是为了方便起见。

r.Host is much easier to call than r.Header.Get("Host") or r.URL.Host . r.Hostr.Header.Get("Host")r.URL.Host更容易调用。

Also to be noted that some routers strip the host from http.Request.URL so http.Request.Host is useful in those cases as well. 还需要注意的是,有些路由器会从http.Request.URL剥离主机,因此http.Request.Host在这些情况下也很有用。

Hence it can be considered that req.Host provides the Host value even when the request header or url has been modified elsewhere. 因此,可以认为req.Host即使在其他地方修改了请求标头或URL时也提供了Host值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM