英文:
What is the difference between `Host` and `URL.Host` for golang `http.Request`?
问题
在开发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
没有给出太多线索。
// 对于服务器请求,Host指定了URL所在的主机。
// 根据RFC 2616,这可以是“Host”头的值,也可以是URL本身中给出的主机名。
// 它可以是“host:port”的形式。对于国际域名,Host可以是Punycode或Unicode形式。
// 如果需要,可以使用golang.org/x/net/idna将其转换为任一格式。
//
// 对于客户端请求,Host可选地覆盖Host头进行发送。如果为空,Request.Write方法将使用URL.Host的值。Host可以包含国际域名。
Host string
在请求中,我认为有两个主机值:URI行和Host
头,例如:
GET http://localhost:8080/ HTTP/1.1
Host: localhost:8080
但这并没有解决问题,反而引入了更多问题:
- 为什么请求中有两个不同的
Host
字段?这不是重复了吗? - 在同一个请求中,这两个
Host
字段可以不同吗? - 在什么情况下应该使用哪一个?
最好附带一个真实的HTTP请求示例来回答这些问题。提前感谢您的帮助。
英文:
When developing golang http application, I use http.Request
a lot. 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.
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.
// 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:
GET http://localhost:8080/ HTTP/1.1
Host: localhost:8080
But it does not solve many problems than it creates:
- Why are there two different
Host
field in request? I mean isn't this a duplicate? - Can the two
Host
fields be different in the same request? - Which one should I use for what situation?
Answers with a real HTTP request example would be the best. Thanks in advance.
答案1
得分: 49
r.URL
字段是通过解析HTTP请求URI创建的。
r.Host
字段是Host请求头的值。它与调用r.Header.Get("Host")
的结果相同。
如果在网络上的HTTP请求如下所示:
GET /pub/WWW/TheProject.html HTTP/1.1
Host: www.example.org:8080
那么r.URL.Host
是"",r.Host
是www.example.org:8080
。
r.URL.Host
和r.Host
的值几乎总是不同的。在代理服务器上,r.URL.Host
是目标服务器的主机,而r.Host
是代理服务器本身的主机。当不通过代理连接时,客户端在请求URI中不指定主机。在这种情况下,r.URL.Host
是空字符串。
如果您不是在实现代理,那么应该使用r.Host
来确定主机。
英文:
The r.URL
field is created by parsing the HTTP request URI.
The r.Host
field is the value of the Host request header. It's the same value as calling r.Header.Get("Host")
.
If the HTTP request on the wire is:
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
.
The value of r.URL.Host
and r.Host
are almost always different. 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. When not connecting through a proxy, the client does not specify a host in the request URI. In this scenario, r.URL.Host
is the empty string.
If you are not implementing a proxy, then you should use r.Host
to determine the host.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论