HTTP 重定向是服务器向客户端发出的指示,告诉客户端需要访问另一个 URL。重定向通常用于改变请求的目标地址,例如在网站改版时,将旧地址重定向到新地址,或者将 HTTP 请求重定向到 HTTPS。
重定向类别:
永久重定向、临时重定向、特殊重定向
永久重定向
这种重定向操作是永久性的。它表示原 URL 不应再被使用,而选用新的 URL 替换它。搜索引擎机器人、RSS 阅读器以及其他爬虫将更新资源原始的 URL。
301 永久重定向:
状态码:301
状态文本:
Moved Permanently
处理方法:
GET
方法不会发生变更。其他方法有可能会变更为GET
方法。用途:网站重构:用于将旧的 URL 永久重定向到新的 URL。浏览器会记住这个重定向,并在未来自动访问新地址。
例如,将 http://a.com 重定向到 http://b.com。
308 永久重定向:
状态码:308
状态文本:
Permanent Redirect
处理方法:与 301 不同,308 明确要求重定向时保持原始请求的方法和请求体。这对于需要保持请求数据的应用程序(如表单提交)尤为重要。
用途:API 版本迁移:将旧版本的 API 请求重定向到新版本,同时保留请求方法和数据。网站迁移:网站改版或域名变更时,确保所有请求都永久指向新地址。HTTPS 强制:将所有 HTTP 请求永久重定向到 HTTPS,以提升安全性。
例如,将
http://example.com/api/v1
永久重定向到https://example.com/api/v2
临时重定向
302临时重定向:
状态码:302
状态文本:
Found 或 Moved Temporarily
处理方法:
GET
方法不会发生变更。其他方法有可能会变更为GET
方法。用途:用于临时重定向,表明请求的资源暂时位于不同的 URL。浏览器不会记住这个重定向。这个重定向,并在未来自动访问新地址。
例如,临时将一个页面重定向到维护页面。
303临时重定向:
状态码:303
文本:
See Other
处理方法:
GET
方法不会发生变更,其他方法会变更为GET
方法(消息主体丢失)。用途:用于
PUT
或POST
请求完成之后重定向,来防止由于页面刷新导致的操作的重复触发。例如,提交表单后将用户重定向到确认页面。
307临时重定向:
状态码:307
文本:
Temporary Redirect
处理方法:方法和消息主体都不发生变化。客户端在重定向时必须使用与原始请求相同的方法和请求体,该状态码优于 302 状态码。
用途:维护页面:网站维护期间,将所有请求临时重定向到维护页面,并在维护结束后恢复。负载均衡:临时将流量重定向到备用服务器,以应对高流量或服务器维护。A/B 测试:临时重定向部分流量到不同的测试页面。
例如,假设我们将
http://example.com/api/resource
临时重定向到http://backup.example.com/api/resource
特殊重定向
304 特殊重定向:
状态码:304
文本:
Not Modified
用途:当客户端(如浏览器)请求一个资源时,如果它已经有这个资源的缓存版本,它会在请求头中包含一些条件性请求头,例如
If-Modified-Since
或If-None-Match
,以询问服务器自上次缓存以来资源是否有更新。如果资源没有更新,服务器会返回 304 状态码,并且不会在响应体中包含资源内容。客户端可以使用其本地缓存的版本,这样可以减少网络带宽的使用和加载时间。缓存控制头部:为了更好地控制缓存,服务器还可以使用一些缓存控制头部,例如:Cache-Control:指定缓存指令,例如
max-age
、no-cache
、no-store
等。Expires:指定资源过期的日期和时间。ETag:提供资源的唯一标识符,用于条件请求。
300 特殊重定向:状态码:304
文本:
Multiple Choice
用途:不常用:所有的选项在消息主体的 HTML 页面中列出。鼓励在
Link
标头中加入机器可读的rel=alternate
指定重定向的方式
http重定向可以使用Nginx等web服务器,或应用服务器返回。
但HTTP 重定向不是定义重定向的唯一方法。还有两个:
借助 HTML 的
<meta>
元素的 HTML 重定向机制借助 DOM 的 JavaScript 重定向机制。
HTML 重定向机制
HTTP 重定向是创建重定向的最佳方式,但是有时候你并不能控制服务器。针对这些特定的应用情景,可以尝试在页面的 <head>
中添加一个 <meta>
元素,并将其 http-equiv
属性的值设置为 refresh
。当显示页面的时候,浏览器会检测该元素,然后跳转到指定的页面。
HTMLCopy to Clipboard
<head>
<meta http-equiv="Refresh" content="0; URL=http://example.com/" />
</head>
content
属性的值开头是一个数字,指示浏览器在等待该数字表示的秒数之后再进行跳转。建议始终将其设置为 0
来获取更好的无障碍体验。
显然,该方法仅适用于 HTML 页面(或类似的页面),然而并不能应用于图片或者其他类型的内容。
JavaScript 重定向机制
在 JavaScript 中,重定向机制的原理是设置 window.location
的属性值,然后加载新的页面。
JSCopy to Clipboard
window.location = "https://example.com/";
与 HTML 重定向机制类似,这种方式并不适用于所有类型的资源,并且显然只有在执行 JavaScript 的客户端上才能使用。另外一方面,它也提供了更多的可能性:比如在只有满足了特定的条件的情况下才可以触发重定向机制的场景。
优先级
由于存在上述三种 URL 重定向机制,那么在多种方法同时设定的情况下,哪种方法会首先起作用呢?
HTTP 协议的重定向机制永远最先触发——它们甚至在没有传输页面的情况下就已经存在。
HTML 的重定向机制 (
<meta>
) 会在没有任何 HTTP 协议重定向的情况下触发。JavaScript 的重定向机制总是作为最后诉诸的手段,并且只有在客户端开启了 JavaScript 的情况下才起作用。
如果可能,请采用 HTTP 协议的重定向机制,而不要使用 <meta>
元素重定向。假如开发人员修改了 HTTP 重定向,而忘记修改 HTML 页面的重定向,那么二者就会不一致,最终结果或者出现无限循环,或者导致其他噩梦的发生。
实践
将我的博客由http://dzbook.top
临时重定向到https://dzbook.top
,采用307临时重定向,如下为Nginx配置。
server {
listen 80;
listen [::]:80;
server_name dzbook.top;
root /usr/share/nginx/html;
# 重定向到https
location / {
return 307 https://dzbook.top;
}
}
如下图,当我通过http访问我的网站时,将会被重定向到https