HTTP 中的重定向
URL 重定向,也称为URL 转发,是一种为页面、表单、整个网站或 Web 应用程序提供多个 URL 地址的技术。HTTP 为此操作提供了一种特殊的响应,称为 HTTP 重定向。
重定向可实现众多目标
- 网站维护或停机期间的临时重定向
- 更改网站 URL 后,为保留现有链接/书签的永久重定向;上传文件时的进度页面等。
原理
在 HTTP 中,重定向是由服务器向请求发送特殊的重定向响应触发的。重定向响应具有以 3
开头的状态码和包含要重定向到的 URL 的 Location
标头。
当浏览器收到重定向时,它们会立即加载 Location
标头中提供的新 URL。除了额外的往返带来的少量性能损失外,用户很少会注意到重定向。
重定向有多种类型,分为三类
永久重定向
这些重定向旨在永久有效。它们意味着原始 URL 不应再使用,并被新 URL 替换。搜索引擎机器人、RSS 阅读器和其他爬虫会更新资源的原始 URL。
代码 | 文本 | 方法处理 | 典型用例 |
---|---|---|---|
301 |
永久移动 |
GET 方法不变。其他方法可能会或可能不会更改为 GET 。[1] |
网站重组。 |
308 |
永久重定向 |
方法和正文不变。 | 网站重组,包含非 GET 链接/操作。 |
[1] 规范无意允许方法更改,但现有用户代理确实会更改其方法。308
的创建是为了消除使用非 GET
方法时行为的模糊性。
临时重定向
有时无法从其规范位置访问请求的资源,但可以从其他位置访问。在这种情况下,可以使用临时重定向。
搜索引擎机器人和其他爬虫不会记住新的临时 URL。临时重定向也用于创建、更新或删除资源时,以显示临时进度页面。
代码 | 文本 | 方法处理 | 典型用例 |
---|---|---|---|
302 |
已找到 |
GET 方法不变。其他方法可能会或可能不会更改为 GET 。[2] |
Web 页面因不可预见的原因暂时不可用。 |
303 |
查看其他 |
GET 方法不变。其他方法更改为 GET (正文丢失)。 |
在 PUT 或 POST 后用于重定向,这样刷新结果页面就不会重新触发操作。 |
307 |
临时重定向 |
方法和正文不变 | Web 页面因不可预见的原因暂时不可用。当网站上存在非 GET 操作时,比 302 更好。 |
[2] 规范无意允许方法更改,但现有用户代理确实会更改其方法。307
的创建是为了消除使用非 GET
方法时行为的模糊性。
特殊重定向
304
(未修改)将页面重定向到本地缓存的副本(已过期),而 300
(多项选择)是手动重定向:浏览器以网页形式显示的正文列出了可能的重定向,用户点击其中一个进行选择。
代码 | 文本 | 典型用例 |
---|---|---|
300 |
多项选择 |
不多:选项在正文中的 HTML 页面中列出。鼓励将机器可读的选项作为带有 rel=alternate 的 Link 标头发送。 |
304 |
未修改 |
针对重新验证的条件请求发送。指示缓存的响应仍然有效且可以使用。 |
指定重定向的替代方式
HTTP 重定向不是定义重定向的唯一方式。还有另外两种方式
HTML 重定向
HTTP 重定向是创建重定向的最佳方式,但有时您无法控制服务器。在这种情况下,请尝试在页面的 <head>
中使用 <meta>
元素,并将其 http-equiv
属性设置为 Refresh
。显示页面时,浏览器将转到指示的 URL。
<head>
<meta http-equiv="Refresh" content="0; URL=https://example.com/" />
</head>
content
属性应以一个数字开头,指示浏览器在重定向到给定 URL 之前应等待多少秒。为了符合辅助功能要求,始终将其设置为 0
。
显然,此方法仅适用于 HTML,不能用于图像或其他类型的内容。
JavaScript 重定向
JavaScript 中的重定向通过将 URL 字符串设置为 window.location
属性来执行,从而加载新页面
window.location = "https://example.com/";
与 HTML 重定向一样,这不能对所有资源都有效,而且显然,这只适用于执行 JavaScript 的客户端。另一方面,有更多可能性:例如,您可以仅在满足某些条件时触发重定向。
优先顺序
有三种触发重定向的方式,可以同时使用多种方式。但哪个先应用?
- HTTP 重定向总是首先执行——它们甚至在没有传输页面时就存在了。
- 有点令人惊讶的是,JavaScript 重定向在 HTML 重定向之前执行。这是因为
<meta>
重定向发生在页面完全加载之后,也就是所有脚本执行之后。 - 如果页面加载之前没有执行任何 HTTP 重定向或 JavaScript 重定向,则执行 HTML 重定向(
<meta>
)。 - 如果在页面加载后发生任何 JavaScript 重定向(例如,点击按钮时),如果页面尚未被先前的方法重定向,它将最后执行。
如果可能,请使用 HTTP 重定向,不要添加 <meta>
元素重定向。如果有人更改了 HTTP 重定向但忘记更改 HTML 重定向,重定向将不再相同,这可能导致无限循环或其他噩梦。
用例
重定向有许多用例,但由于每次重定向都会影响性能,因此应将其使用降至最低。
域名别名
理想情况下,每个资源都有一个位置,因此有一个 URL。但资源有替代名称的原因
- 扩大您网站的覆盖范围
-
一个常见的情况是,网站位于
www.example.com
,但从example.com
访问也应该有效。因此,会设置将example.com
重定向到www.example.com
。您还可以从您的域名的常见同义词或常见拼写错误进行重定向。 - 迁移到新域名
-
例如,您的公司改名了,但您希望现有链接或书签仍然可以通过新名称找到您。
- 强制 HTTPS
-
对您网站的
http://
版本的请求将重定向到您网站的https://
版本。
保持链接有效
重构网站时,URL 会更改。即使您更新网站链接以匹配新 URL,您也无法控制外部资源使用的 URL。
您不想破坏这些链接,因为它们会带来有价值的用户并帮助您的 SEO,因此您会设置从旧 URL 到新 URL 的重定向。
注意:此技术适用于内部链接,但尽量避免内部重定向。重定向会产生显着的性能成本(因为会发生额外的 HTTP 请求)。如果您可以通过纠正内部链接来避免它,您应该修复这些链接。
对不安全请求的临时响应
不安全的请求会修改服务器的状态,用户不应无意中重新发送它们。
通常,您不希望用户重新发送 PUT
、POST
或 DELETE
请求。如果您将此请求的结果作为响应提供,则按重新加载按钮将重新发送请求(可能在确认消息之后)。
在这种情况下,服务器可以针对包含正确信息的 URL 发回 303
(查看其他)响应。如果按下重新加载按钮,只会重新显示该页面,而不会重播不安全的请求。
对长时间请求的临时响应
某些请求可能需要在服务器上花费更多时间,例如计划稍后处理的 DELETE
请求。在这种情况下,响应是 303
(查看其他)重定向,该重定向链接到一个页面,指示操作已安排,并最终通知其进度或允许取消它。
在常用服务器中配置重定向
Apache
重定向可以在服务器配置文件或每个目录的 .htaccess
中设置。
mod_alias
模块具有 Redirect
和 RedirectMatch
指令,默认情况下会设置 302
重定向
<VirtualHost *:443>
ServerName example.com
Redirect / https://www.example.com
</VirtualHost>
URL https://example.com/
将重定向到 https://www.example.com/
,其下的任何文件或目录也将重定向(https://example.com/some-page
将重定向到 https://www.example.com/some-page
)
RedirectMatch
作用相同,但接受正则表达式来定义受影响的 URL 集合
RedirectMatch ^/images/(.*)$ https://images.example.com/$1
images/
目录中的所有文档都将重定向到不同的域。
如果您不想要临时重定向,可以使用额外的参数(要使用的 HTTP 状态码或 permanent
关键字)来设置不同的重定向
Redirect permanent / https://www.example.com
# …acts the same as:
Redirect 301 / https://www.example.com
mod_rewrite
模块也可以创建重定向。它更灵活,但也更复杂一些。
Nginx
在 Nginx 中,您为要重定向的内容创建一个特定的服务器块
server {
listen 80;
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}
要将重定向应用于目录或仅某些页面,请使用 rewrite
指令
rewrite ^/images/(.*)$ https://images.example.com/$1 redirect;
rewrite ^/images/(.*)$ https://images.example.com/$1 permanent;
IIS
在 IIS 中,您使用 <httpRedirect>
元素来配置重定向。
重定向循环
重定向循环发生在已跟踪的重定向之后又出现额外重定向时。换句话说,存在一个永远不会结束的循环,并且永远找不到页面。
大多数情况下,这是一个服务器问题,如果服务器能够检测到它,它会返回 500
Internal Server Error
。如果您在修改服务器配置后不久遇到此类错误,则很可能是重定向循环。
有时,服务器不会检测到它:重定向循环可能跨越多个服务器,每个服务器都没有完整的视图。在这种情况下,浏览器会检测到它并显示错误消息。Firefox 显示
Firefox 检测到服务器以一种永远不会终止的方式重定向此地址的请求。
……而 Chrome 显示
此网页存在重定向循环
在这两种情况下,用户都无能为力(除非他们一方发生损坏,例如缓存或 Cookie 不匹配)。
避免重定向循环很重要,因为它们会完全破坏用户体验。
另见
- 3XX 重定向响应状态
Location
标头- 用于使用 JavaScript 进行重定向的
window.location
属性