当我在浏览器的地址栏中输入一个网站的url时,浏览器会根据url发送一个请求来获取资源。但是,当我去不同的网站(google.com、amazon.com等)时,初始化页面的请求,在不同的网站有不同的头。
如果浏览器在第一次初始化时,只有这个资源的URL信息,那么浏览器从哪里得到一组请求的头文件来加载页面?
例如,当我去google.com时,浏览器会发送这样的请求头。
:authority: www.google.com
:method: GET
:path: /
:scheme: https
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7
cache-control: max-age=0
sec-fetch-dest: document
sec-fetch-mode: navigate
sec-fetch-site: same-origin
sec-fetch-user: ?1
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36
对于amazon.com,请求的头信息是不同的。
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ru-RU;q=0.8,ru;q=0.7
Connection: keep-alive
Host: amazon.com
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36
当你在地址栏中输入一个URL时,这需要翻译成HTTP请求。
因此,输入www.google.com 意味着你需要 GET
默认页(/
)从该服务器。这在第一个请求的前4行中基本都有涉及。
浏览器也知道它可以用什么类型的格式?accept
. 大多数情况下,我们提供的HTML回所以 text/html
当然是在那里,但我们也接受其他格式 - 包括完全通用的 */*
顺便说一句! :-)
请求经常被压缩(用 gzip
, deflate
或较新的 brotli (br
)格式),这样浏览器就会告诉服务器它支持其中的哪一种,并在 accept-encoding
头。
当你安装浏览器时,你还设置了一个默认语言,这样我们就可以告诉服务器。有些服务器会根据这个返回不同的内容。
然后是一些安全头(我不会去讨论这些,因为相当复杂)。
最后我们还有 user-agent
头部,这基本上是浏览器告诉服务器是Chrome,还是Firefox或其他什么的地方。但对于 历史原因 它比单纯的 "Chrome "要长得多。
因此,基本上请求头是浏览器发送给服务器的东西,以提供更多关于浏览器和它的功能的信息。对于刚刚输入浏览器的请求,无论URL是什么,请求头基本上都是一样的。对于页面提出的额外请求--例如通过JavaScript代码提出的请求,如果它添加了更多的头信息,它们可能会有所不同。
至于你举的两个例子请求的区别。
谷歌使用HTTP2(如果使用Chrome浏览器,则使用QUIC,但就目前而言,就这个问题而言,基本上就是HTTP2)。如果你在开发者工具中添加选项协议栏,就可以看到这一点。
HTTP2与HTTP1相比,有几个变化,即
GET / HTTP/1.1
)被转换为以冒号开头的伪头 (:method: GET
, :path: /
.等)。)Host
基本上是 :authority
在HTTP2中。:scheme
在HTTP2中基本是新的,因为以前它并不是明确的HTTP请求的一部分,而是在连接层处理。Connection
在HTTP2中是失效的。即使在HTTP1.1中,它也默认为 keep-alive
所以上面的头是没有必要的,但很多浏览器和其他客户端出于历史原因发送了它。我想这解释了所有的差异。
那么浏览器是如何知道是使用HTTP2还是HTTP1.1的呢?哪一个 Stack Overflow上已经有了答案但基本上是在HTTPS会话建立时决定,如果服务器建议它可以支持HTTP2,而浏览器想使用它。