Host 是 HTTP 1.1 协议中新增的一个请求头,主要用来实现虚拟主机技术。
虚拟主机(virtual hosting)即共享主机(shared web hosting),可以利用虚拟技术把一台完整的服务器分成若干个主机,因此可以在单一主机上运行多个网站或服务。
举个栗子,有一台 ip 地址为 61.135.169.125 的服务器,在这台服务器上部署着谷歌、百度、淘宝的网站。为什么我们访问 https://www.google.com 时,看到的是 Google 的首页而不是百度或者淘宝的首页?原因就是 Host 请求头决定着访问哪个虚拟主机。
在使用tomcat的时候我们可以配置多个host,以此来实现一个web服务器上部署网站,每一个网站有不同的host,就像下面这样
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="localhost1" appBase="webapps1"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
<!--
需要注意的是,localhost1是不能被DNS解析到127.0.0.1的,这需要我们自己去配置host映射
localhost不用进行配置,因为DNS会直接把该地址解析为127.0.0.1
-->
那么tomcat是如何知道把你的请求对应到哪个网站的呢?首先我们清楚我们的浏览器的一次请求,虽然我们写的是url,但是最后会被DNS解析成ip地址然后进行访问,所以说tomcat肯定不能使用请求url来进行判断,因为DNS解析之后我们请求的url就没有了。tcp/ip协议可不认识什么host,他也不知道你的请求地址,他只管把数据发送到对应ip的对应端口上去。所以说你直接发给tomcat的请求,他是不能知道到底要送到他内部的哪个网站去处理的,怎么进行判断呢?就是利用Http协议的Host请求头,根据请求头映射到对应的网站上,所以说我们一般的请求都会带上host请求头。
我们可以尝试一下,构建一个没有Host请求头的Http请求
public static void main(String[] args) throws UnsupportedEncodingException {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 创建Get请求
HttpPost httpPost = new HttpPost("http://localhost:8080");
httpPost.setHeader("Host", "111");
// 响应模型
CloseableHttpResponse response = null;
Header[] allHeaders1 = httpPost.getAllHeaders();
for (Header header : allHeaders1) {
System.out.println(header);
}
try {
response = httpClient.execute(httpPost);
Header[] allHeaders = response.getAllHeaders();
for (Header allHeader : allHeaders) {
System.out.println(allHeader);
}
HttpEntity responseEntity = response.getEntity();
System.out.println("响应状态为:" + response.getStatusLine());
if (responseEntity != null) {
System.out.println("响应内容长度为:" + responseEntity.getContentLength());
System.out.println("响应内容为:" + EntityUtils.toString(responseEntity, "UTF-8"));
}
} catch (ParseException | IOException e) {
e.printStackTrace();
} finally {
try {
if (httpClient != null) {
httpClient.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
可以发现能正常返回结果,为什么?因为tomcat中存在一个defaultHost,如下图
当没有任何的host能映射到我们对应的请求头,就会使用这个默认的host