Location
用法
服务器在将客户端引导至不同 URL 时包含 Location。该头出现在两种场景中:重定向响应和资源创建。
对于重定向,Location 值告诉客户端将下一个请求发送到何处。其行为取决于状态码:
对于资源创建,201 Created 响应会包含指向新创建资源的 Location。这为客户端提供了直接引用,无需再进行后续查找。
Location 值同时接受绝对 URL 和相对 URL。相对 URL 相对于请求 URI 进行解析。
注意
Location 头与 Content-Location 头用途不同。Location 指向重定向目标或新创建的资源。Content-Location 标识所返回表示的直接 URL。
注意
搜索引擎会跟随重定向,并在永久重定向(301、308)时将链接权重(排名价值)转移到目标 URL。临时重定向(302、307)并不总是传递链接权重。在 URL 迁移期间使用正确的状态码可保留搜索排名。
URL
其值是一个指向目标位置的 URI 引用。
Location: <url>
该 URL 要么是带方案和主机的绝对 URI,要么是相对于请求 URI 解析的相对引用。
示例
从旧域名到新域名的永久重定向告诉客户端更新书签和链接。对于 301,客户端被允许将请求方法从 POST 改为 GET。
HTTP/1.1 301 Moved Permanently
Location: https://new.example.re/products
一个 308 永久重定向保留原始请求方法,使该重定向对 POST 和其他非 GET 请求都是安全的。
HTTP/1.1 308 Permanent Redirect
Location: https://new.example.re/products
在通过 POST 请求创建资源后,服务器返回 201 以及新资源的 Location。
HTTP/1.1 201 Created
Location: /api/orders/7891
Content-Type: application/json
表单提交后的 303 响应使用 GET 将客户端重定向到结果页面。
HTTP/1.1 303 See Other
Location: /search/results?q=http+headers
故障排查
重定向失败通常表现为无限循环、损坏的 URL 或响应中缺少头。
重定向循环。Location 头指回当前 URL,或指向另一个又重定向回来的 URL,从而形成无限循环。浏览器在达到设定的跳转次数后会停止,并显示 ERR_TOO_MANY_REDIRECTS 错误。使用 curl -L -v 追踪跳转链以识别循环。常见原因包括:某服务器规则将 HTTP 重定向到 HTTPS,而负载均衡器又将 HTTPS 重定向回 HTTP;或者匹配目标 URL 的 nginx return 301 规则。在 nginx 中,收紧使用 if ($scheme = http) 守卫并对两种协议都进行测试。
相对 URL 未被正确解析。Location 值接受相对引用,但某些较旧的客户端和中间设备期望绝对 URL。像 /new-page 这样的路径相对于请求 URI 解析。省略前导斜杠会创建一个相对于当前目录解析的相对路径,从而产生意外结果。使用带方案和主机的绝对 URL 以避免歧义。
3xx 响应缺少 Location 头。带有重定向状态码却没有 Location 头的响应使客户端没有目标可去。浏览器会显示空白页面或错误。用 curl -I https://example.re/old-path 检查服务器响应并确认该头存在。在 Apache 中,Redirect 和 RedirectMatch 指令总会包含该头。自定义应用代码必须显式设置该头。
重定向目标中的协议不匹配。在 HTTPS 站点上,Location 头中的 HTTP URL 会触发混合内容警告,或在严格环境中阻止重定向。确保目标 URL 与来源协议匹配或升级到 HTTPS。在 nginx 中,使用 return 301 https://$host$request_uri; 以保持安全方案。
片段未在重定向间保留。原始 URL 中的片段标识符(#section)不会在 Location 头中转发。仅当目标 URL 本身不包含片段时,浏览器才会将原始片段重新附加到重定向目标上。如果 Location 值包含不同的片段,则原始片段丢失。服务器端代码无法访问片段,因为浏览器不会在请求中发送它们。
调试重定向链。运行 curl -L -v https://example.re/start 以跟随所有重定向,并查看每一跳的状态码和头。DevTools Network 选项卡也会显示完整的链路。按文档类型过滤,以将重定向响应与子资源请求区分开。