点击页面 “链接” 时的跳转是怎样的呢?
浏览器首先要解析链接文字里的 URI,再用这个 URI 发起一个新的 HTTP 请求,获取响应报文后就会切换显示内容,渲染出新 URI 指向的页面
这样的跳转动作是由浏览器的使用者主动发起的,可以称为 “主动跳转”,还有一类跳转是由服务器发起的,浏览器使用者无法控制,当浏览器请求一个URL时,服务器返回一个重定向指令,告诉浏览器地址已经变了,麻烦使用新的URL再重新发送新请求相对的称为“被动跳转”,这在 HTTP 协议里有个专门名词,叫“重定向”
重定向的过程
我用 Chrome 访问 http://www.chrono.com/18-1 ,它会使用 302 立即跳转到 /index.html
从上面可以看出,这一次重定向实际发送了两次 HTTP 请求,第一次请求返回 302,然后第二个请求就被重定向到了 ./index.html 如果不用开发者工具,完全看不到这个跳转过程,即重定向是 “用户无感知的”
第一个请求返回的响应报文
这里的Location字段属于响应字段,出现在响应报文里,只有配合 301/302 状态码才有意义,它标记了服务器要求重定向的 URI,这里就是要求浏览器跳转到 index.html
浏览器收到 301/302 报文,会检查响应头有没有 Location,如果有,就从字段里提取 URI,发出新的 HTTP 请求,相当于自动替我们点击这个链接
在 Location里的 URI 既可以使用绝对 URI,也可以使用相对 URI。绝对 URI 就是完整形式的,包括 scheme、host:port、path等,而相对 URI 就是胜利了 scheme 和 host:port,只有 path 和 query 部分,不是完整的,但是可以从请求上下文计算得到
例如,刚才的实验例子里的“Location: /index.html”用的就是相对URI。它没有说明访问URI的协议和主机,但因为是由“http://www.chrono.com/18-1”重定向返回的响应报文,所以浏览器就可以拼出完整的URI:http://www.chrono.com/index.html
注意,在重定向时如果只是在站内跳转,可以放心地使用相对URI。但如果要跳转到站外,就必须用绝对URI。例如,如果想跳转到Nginx官网,就必须在“nginx.org”前把“http://”都写出来,否则浏览器会按照相对URI去理解,得到的就会是一个不存在的URI :http://www.chrono.com/nginx.org
重定向状态码
最常见的重定向状态码就是301和302,另外还有几个不太常见的,例如303、307、308等。它们最终的效果都差不多,让浏览器跳转到新的URI,但语义上有一些细微的差别
301俗称“永久重定向”(Moved Permanently),意思是原URI已经“永久”性地不存在了,今后的所有请求都必须改用新的URI
浏览器看到301,就知道原来的URI“过时”了,就会做适当的优化。比如历史记录、更新书签,下次可能就会直接用新的URI访问,省去了再次跳转的成本。搜索引擎的爬虫看到301,也会更新索引库,不再使用老的URI
302俗称“临时重定向”(“Moved Temporarily”),意思是原URI处于“临时维护”状态,新的URI是起“顶包”作用的“临时工”。浏览器或者爬虫看到302,会认为原来的URI仍然有效,但暂时不可用,所以只会执行简单的跳转页面,不记录新的URI,也不会有其他的多余动作,下次访问还是用原URI
303 See Other:类似302,但要求重定向后的请求改为GET方法,访问一个结果页面,避免POST/PUT重复操作
307 Temporary Redirect:类似302,但重定向后请求里的方法和实体不允许变动,含义比302更明确
308 Permanent Redirect:类似307,不允许重定向后的请求变动,但它是301“永久重定向”的含义
303、307、308 有的浏览器和服务器可能不支持,开发要谨慎,测试确认浏览器的效果后才能使用
重定向的应用场景
-
需要重定向的一个常见原因是“资源不可用”,需要用另一个新的 URI 来代替。不可用的原因很多,比如域名变更、服务器变更、网站改版、系统维护、这些都会导致原 URI 指向的资源无法访问,为了避免 404 ,就需要使用重定向跳转到新的 URI,继续服务。
-
另一个常见原因是“避免重复”,让多个网址都跳转到一个 URI,增加访问入口的同时还会增加额外的工作量。例如有的网站会申请多个名称类似的域名,然后把它们再重定向到主站上
-
考虑的就是“永久”和“临时”的问题了,也就是选择301还是302
302 的含义是“永久”的,如果域名、服务器、网站架构发生了大幅度的改变,比如启用了新域名、服务器切换到了新机房、网站目录层次重构,这些都算是“永久性” 改变。必须用 301 永久重定向,通知浏览器和搜索引擎更新到新地址,也是搜索引擎优化要考虑的因素之一。
302 的含义是“临时”的,原来的URI在将来的某个时间点还会恢复正常,常见的应用场景就是系统维护,把网站重定向到一个通知页面,告诉用户过一会儿再来访问。另一种用法就是“服务降级”,比如在双十一促销的时候,把订单查询、领积分等不重要的功能入口暂时关闭,保证核心服务能够正常运行
重定向相关问题
-
性能损耗,重定向的机制决定了一个跳转会有两次请求-应答,比正常放完多一次。虽然 301/302 报文很小,但大量的跳转对服务器的影响也是不可忽视的。站内重定向还好说,可以长连接复用,站外重定向就要开两个连接,如果网络连接质量差,那成本可就高多了,会影响用户体验
-
循环跳转,如果重定向的策略设置欠考虑,可能会出现 A=>B=>C=>A 的无限循环,所以HTTP协议特别规定,浏览器必须具有检测“循环跳转”的能力,在发现这种情况时应当停止发送请求并给出错误提示。如下模拟情况:
注意转发和重定向的区别在于,转发是在Web服务器内部完成的,对浏览器来说,它只发出了一个HTTP请求,所以浏览器地址栏不会变,他不知道该请求在 Web 服务器内部实际做了一次转发。