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

时间:2017-03-21 08:17:30

标签: http go

在开发golang http应用程序时,我经常使用http.Request。访问请求主机地址时,我会使用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)
}

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

在我看来,请求中有两个主机值:uri行和Host标题,如:

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

但它并没有解决许多问题,而是解决了这个问题:

  1. 为什么请求中有两个不同的Host字段?我的意思是,这不是重复的吗?
  2. 同一个请求中两个Host字段是否可以不同?
  3. 我应该在哪种情况下使用哪一个?
  4. 使用真实HTTP请求示例的答案将是最好的。提前谢谢。

2 个答案:

答案 0 :(得分:17)

r.URL字段是通过解析HTTP请求URI创建的。

r.Host字段是Host request header的值。它与调用r.Header.Get("Host")的值相同。

如果线路上的HTTP请求是:

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

然后r.URL.Host为“”而r.Hostwww.example.org:8080

r.URL.Hostr.Host的价值几乎总是不同的。在代理服务器上,r.URL.Host是目标服务器的主机,r.Host是代理服务器本身的主机。未通过代理连接时,客户端不会在请求URI中指定主机。在这种情况下,r.URL.Host是空字符串。

如果您没有实施代理,则应使用r.Host来确定主机。

答案 1 :(得分:3)

基本上http.Request.Host是为了方便。

r.Hostr.Header.Get("Host")r.URL.Host更容易致电。

另外需要注意的是,有些路由器会从http.Request.URL剥离主机,因此http.Request.Host在这些情况下也很有用。

因此可以认为req.Host即使在其他地方修改了请求标头或URL时也提供了Host值。