浏览器在访问 HTTP 协议非 HTTPS 的站点时,通常会发生 301 重定向,那么整个请求响应流程是怎样的?接下来我们深入分析一下。
分析
首先,我们明白,这是一个 HTTP 层面的行为,底层依赖 TCP 协议进行可靠传输。
[!tips] 前置知识
HTTP 端口为 80,HTTPS 端口为 443
301 是 HTTP 响应状态码,表示永久重定向,即请求的资源已永久移动到新的位置。
理论分析
一、初始请求阶段
1
| 用户输入URL → DNS解析 → TCP三次握手 → 发送HTTP请求
|
- 用户输入 URL:用户在浏览器地址栏输入一个 URL(比如
http://example.com )并按下回车。 - DNS 解析:浏览器解析 URL 中的域名,通过 DNS 获取对应的 IP 地址。如果涉及到重定向,可能在 DNS 层面就有 CNAME 等记录。
- 建立 TCP 连接:浏览器根据 IP 地址和端口 (默认 80 或 443)与服务器建立 TCP 连接。这一步是 TCP 协议的工作,包括三次握手。
- 发送 HTTP 请求:通过已建立的 TCP 连接,浏览器发送 HTTP 请求。例如,一个 GET 请求到根路径/。
客户端请求报文示例:
1
2
| GET / HTTP/1.1
Host: example.com
|
二、服务器响应阶段
1
| 服务器处理 → 判断需重定向 → 生成301响应 → 通过TCP回传
|
- 服务器处理请求:服务器收到请求后,判断是否需要重定向到新的 URL。
- 服务器发送一个 HTTP 响应,状态码为 301,并在响应头中包含
Location: https://example.com(假设跳转到 HTTPS)。
服务器响应示例:
1
2
3
4
| HTTP/1.1 301 Moved Permanently
Location: https://example.com/
Content-Type: text/html
Content-Length: ...
|
服务器是如何判断的呢?以 Nginx 为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| server {
listen 80;
server_name example.com;
# 对HTTP请求重定向到HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert;
ssl_certificate_key /path/to/key;
location / {
root html;
index index.html;
}
}
|
三、浏览器处理阶段
1
| 收到301响应 → 解析新URL → (可能的新TCP连接) → 发送新请求
|
- 浏览器处理重定向:浏览器收到 301 响应后,会从响应头中读取 Location 字段,获取新的 URL,然后自动向这个新 URL 发起新的请求。注意:对于 301 状态码,浏览器通常会缓存重定向信息,下次访问原 URL 时直接跳转到新 URL,而不必再向原 URL 发送请求。
- 向新 URL 发起请求:浏览器使用新 URL,可能重新进行 DNS 解析(如果域名变了)、建立 TCP 新连接(如果需要),然后发送 HTTP 请求。
- 服务器响应新请求:服务器返回正常的 200 状态码响应和网页内容。
- 浏览器渲染:浏览器收到响应后,渲染页面。
如果是 HTTP 到 HTTPS 的重定向:
1
| http://example.com:80 → 301 → https://example.com:443
|
必然会新建 TCP 连接,增加 TLS 握手。
TCP 协议层的分析
TCP 连接管理分析
1
2
3
4
5
6
7
8
9
10
11
| sequenceDiagram
Client->>Server: SYN (原始请求连接)
Server->>Client: SYN-ACK
Client->>Server: ACK + HTTP请求
Server->>Client: 301响应
alt 同一主机/端口
Client->>Server: 重用连接发送新请求
else 不同主机/端口
Client->>Server: FIN (关闭连接)
Client->>NewServer: 新建TCP连接
end
|
另外,顺便一提,对性能的影响:
- 额外 RTT:每次新建 TCP 连接增加 1 个 RTT(三次握手)
- TLS 成本:HTTPS 重定向增加 TLS 握手(2-3 个 RTT)
调试分析
我们可以使用工具,进行直观的分析。
- 使用 cURL 工具追踪
1
| curl -v -L http://example.com # -L自动跟随重定向
|
输出显示 TCP 连接建立、请求响应全过程。
这里以访问 baidu.com 为例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
| curl -v -L http://baidu.com
* Host baidu.com:80 was resolved.
* IPv6: (none)
* IPv4: 110.242.74.102, 124.237.177.164, 111.63.65.247, 111.63.65.103
* Trying 110.242.74.102:80...
* Established connection to baidu.com (110.242.74.102 port 80) from 192.168.68.228 port 12061
* using HTTP/1.x
> GET / HTTP/1.1
> Host: baidu.com
> User-Agent: curl/8.16.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 301 Moved Permanently
< Location: http://www.baidu.com/
< Date: Sat, 20 Dec 2025 10:15:39 GMT
< Content-Length: 56
< Content-Type: text/html; charset=utf-8
* Ignoring the response-body
* setting size while ignoring
<
* Connection #0 to host baidu.com:80 left intact
* Issue another request to this URL: 'http://www.baidu.com/'
* Host www.baidu.com:80 was resolved.
* IPv6: (none)
* IPv4: 220.181.111.232, 220.181.111.1
* Trying 220.181.111.232:80...
* Established connection to www.baidu.com (220.181.111.232 port 80) from 192.168.68.228 port 12064
* using HTTP/1.x
> GET / HTTP/1.1
> Host: www.baidu.com
> User-Agent: curl/8.16.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Content-Length: 2381
< Content-Type: text/html
< Pragma: no-cache
< Server: bfe
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
< Date: Sat, 20 Dec 2025 10:15:39 GMT
<
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title> </html>
* Connection #1 to host www.baidu.com:80 left intact
|
- Chrome DevTools 观察
Network 面板查看“状态”一列显示 HTTP 状态码,“连接 ID"字段查看 TCP 连接重用情况。
总结
通过分析 HTTP 301 重定向流程,我们进一步了解 HTTP 通信交互流程,HTTP 协议基于请求-响应模式,底层基于 TCP 协议提供可靠性的通信。理解和掌握这些机制,能帮助我们遇到问题时,能有一个清晰的解决方向。