我们知道,用来传输页面的协议就是HTTP协议,全称是超文本传输协议,而浏览器展示的页面则是用HTML编写的,HTML的全称则是超文本标记语言。你看,都叫做超文本,我在第一篇文章的时候也详细的聊过,超文本区别于文本的本质就是文本中具有超链接的文本。

  当我们点击页面中的超链接,则会跳转到其它超文本页面,对于线性传统结构的文档,是一个根本性的变革。

一、重定向的基本概念和场景

  点击超链接后,浏览器会解析URL,再用这个URL发起一个新的HTTP请求,跳转到其它页面。这样的跳转动作,是由浏览器的使用者发起的,这种跳转叫做“主动跳转”,但是还有一类跳转,是由服务器发起的,浏览器使用者无法控制,也就是“被动跳转”,被动跳转在HTTP中有一个专有的名词,叫做重定向

  重定向的使用场景其实并不少,比如,多个域名指向一个统一的页面。我们可以在浏览器里打开一个新的tab标签,然后输入http://www.baidu.com,看一下,什么效果?

  我们发现会优先有两个请求,一个307,一个200。我们来看下详细的内容:

  我们看下,其实并不复杂,就是重定向到https协议的域名。

  嗯……这就是一个比较常见的重定向场景之一。再比如一些资源的更新,旧的不用了,但是为了不去修改HTML资源访问的代码,紧急解决一些问题,就可以由服务器更改,重定向到新的资源页面。

  详细的内容,我们在后续的讲解和例子中再深入的学习。

二、重定向涉及到的头字段和状态码

  我们要聊的字段其实不多,就一个,就是Location字段,Location字段可以接受绝对地址或者相对地址作为该字段的值,如果是相对地址的话,则会从响应报文的上下文中获取相应的信息,拼出完整的重定向地址。如果重定向只是在站内跳转,比如www.zaking.com跳转到www.zaking.com/index.html,那你可以随便用,但是如果你要跳到别的站点,比如从www.zaking.com跳转到www.baidu.com,则必须使用完整的绝对地址。

  涉及到重定向的状态码则比较多了,我们要能准确地区分出不同的3xx状态码代表的含义。最常见的状态码就是301、302,还有比如303,304,305,306,307我们稍微了解下,注意其语义的区别即可。

  首先,301状态码的意思是Moved Permanently,也就是永久重定向,意味着你访问的资源已经不存在了,今后所有的请求都要使用新的URI。当浏览器看到301状态码时,就知道原来的URI已经过时了,会适当的做一些优化。比如历史记录,更新书签,下次访问的时候,就不会再往旧地址发送请求了。而搜索引擎看到301,也会更新索引库,不会在去爬原来的地址了。

  当然,这里你要知道的就是,这些一切的优化也好,更新也罢,其实都是终端针对协议所做的应用层面的操作。比如,浏览器会根据301来进行优化,搜索引擎也会根据301来实现更新策略,那浏览器不实现行不行?搜索引擎也不做这些额外的无聊的操作,肯定都是可以的~~

  接下来我们说说302,是指临时重定向,也就是说你访问的地址暂时不能用了,先去新的地址访问资源吧。但由于是临时重定向,浏览器也好,搜索引擎也好,还是其它的啥啥也好,都不会做什么优化和更新,只是做个重定向的操作就完事了。

  那么我们再来看看其它的不常用的状态码:

  1. 303,没啥用~意思是See Other,参见其它的意思,但要求重定向后的请求改为 GET 方法,访问一个结果页面,避免 POST/PUT 重复操作;。其实302做的事情,跟303一样,用302就行了。
  2. 304,未修改,Not Modified,如果客户端执行了一个有条件的Get请求,但是请求的资源并没有修改,则会返回304。有条件的Get请求,其实就是指那些带有If-开头的头字段,需要根据这些字段进行一些其它的逻辑处理。了解下就行啦。
  3. 305,Use Proxy,所提供的Location字段的值必须是一个代理服务器的地址。
  4. 306,废弃了。不用管
  5. 307,Temporary Redirect,类似 302,但重定向后请求里的方法和实体不允许变动,含义比 302 更明确。

  所以你看,除了301和302意外,其它大多数的字段要么场景更细节,实践的时候大多数都由302处理了,要么就废弃了。我们熟悉301和302就足够了。

三、重定向的应用场景

  我们之前在聊状态码的时候,强调了301和302的重要性,换句话就是说,其实重定向可以粗略、简单、明了的理解为临时永久的区别。那么针对重定向的使用场景,实际上也是基于临时和永久的区别和特点来实践的。

  那什么时候需要重定向呢?一个最常见的原因就是“资源不可用”,我们需要提供一个新资源的URI来进行后续的使用。至于不可用的原因那就种类繁多千变万化了,比如服务器维护,为了用户使用不受到影响,则会重定向到一个临时的页面,供用户访问。

  另一个原因就是增加访问入口,让多个名字类似的域名指定到同一个主站,增加访问的入口同时还不会增加什么工作量。

  在确定了重定向的场景后,要考虑的就是临时还是永久了。那么针对我们上面提到的两种场景,要用临时还是永久呢?

四、例子

  我们聊完了重定向的核心概念,接下来我们就来写一写例子,在实际的代码实验中,体验下301和302的区别。按照惯例,基本的代码我就不贴在这里了,我只贴核心的部分了噢。首先,我们先来看看临时重定向:

if (parsedUrl.pathname == "/301") {
let sourceCode = fs.readFileSync(
path.resolve(__dirname, "./index.html"),
"utf8"
);
res.writeHead(301, {
Location: "http://www.zaking.com:9001/redirect"
,
});

res.end(sourceCode);
}

  其实就真的很简单,我感觉没啥说的。302的也一样,把上面的头字段改成302就好了。我感觉这例子不用写,结果我就不展示了,大家有兴趣可以自己试下,我们来看点不一样的:

  看到区别么?301临时重定向,如果你不做缓存的设置,那么浏览器会默认缓存原地址,因为浏览器认为你的重定向是临时的,我以后还是要用这个,而302浏览器压根不会缓存,因为觉得这个地址不会再用了,缓存也没用。我们再来看个例子:

// 死循环了
if (parsedUrl.pathname == "/cycle") {
let sourceCode = fs.readFileSync(
path.resolve(__dirname, "./cycle.html"),
"utf8"
);
res.writeHead(302, {
Location: "http://www.zaking.com:9001/back",
});
res.end(sourceCode);
}
if (parsedUrl.pathname == "/back") {
let sourceCode = fs.readFileSync(
path.resolve(__dirname, "./back.html"),
"utf8"
);
res.writeHead(302, {
Location: "http://www.zaking.com:9001/cycle",
});
res.end(sourceCode);
}

  代码没啥哈,重点在于循环跳转,直接造成浏览器压根没法用:

  这是重定向需要尤其注意的问题,咱们现在的重定向链路十分简单,就两个页面来回跳,当你写了复杂的服务器逻辑的时候,很难确定是否会有循环链路的重定向的。

五、总结

  其实关于重定向,最核心的就是301和302了,大家一定要会,没啥好说的。重定向在一定程度上解决了一些场景下的应用方案,但是其实也带来一定的问题,比如,只要重定向就一定会发送一次额外的请求,造成性能的浪费。另外要格外注意的就是循环跳转的问题。

  本篇的东西不多,那就到这里啦,学习这么无聊,下一篇我们来吃点点心。

真正“搞”懂HTTP协议08之重定向的更多相关文章

  1. 真正“搞”懂HTTP协议02之空间穿梭

    时隔四年,这个系列鸽了四年,我终于觉得我可以按照自己的思路和想法把这个系列完整的表达出来了. 想起四年前,那时候还是2018年的六月份,那时候我还工作不到两年,那时候我翻译了RFC2616的部分内容, ...

  2. 真正“搞”懂http协议01—背景故事

    去年读了<图解HTTP>.<图解TCP/IP>以及<图解网络硬件>但是读了之后并没有什么深刻的印象,只是有了一层模糊的脉络,刚好最近又接触了一些有关http的相关内 ...

  3. 真正“搞”懂HTTP协议03之时间穿梭

    上一篇我们简单的介绍了一下DoD模型和OSI模型,还着重的讲解了TCP的三次握手和四次挥手,让我们在空间层面,稍稍宏观的了解了HTTP所依赖的底层模型,那么这一篇,我们来追溯一下HTTP的历史,看一看 ...

  4. 搞懂Redis协议RESP

    RESP (REdis Serialization Protocal) Redis客户端和服务端之间通信的协议.它很简单,建立在TCP协议上,提供简单.高性能.可读性强的数据序列化的规范和语义. 5种 ...

  5. 搞懂分布式技术4:ZAB协议概述与选主流程详解

    搞懂分布式技术4:ZAB协议概述与选主流程详解 ZAB协议 ZAB(Zookeeper Atomic Broadcast)协议是专门为zookeeper实现分布式协调功能而设计.zookeeper主要 ...

  6. 搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法

    搞懂分布式技术2:分布式一致性协议与Paxos,Raft算法 2PC 由于BASE理论需要在一致性和可用性方面做出权衡,因此涌现了很多关于一致性的算法和协议.其中比较著名的有二阶提交协议(2 Phas ...

  7. [转帖]USB-C和Thunderbolt 3连接线你搞懂了吗?---没搞明白.

    USB-C和Thunderbolt 3连接线你搞懂了吗? 2018年11月25日 07:30 6318 次阅读 稿源:威锋网 3 条评论 按照计算行业的风潮,USB Type-C 将会是下一代主流的接 ...

  8. [转帖]从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路

    从HTTP/0.9到HTTP/2:一文读懂HTTP协议的历史演变和设计思路   http://www.52im.net/thread-1709-1-2.html     本文原作者阮一峰,作者博客:r ...

  9. 搞懂分布式技术21:浅谈分布式消息技术 Kafka

    搞懂分布式技术21:浅谈分布式消息技术 Kafka 浅谈分布式消息技术 Kafka 本文主要介绍了这几部分内容: 1基本介绍和架构概览 2kafka事务传输的特点 3kafka的消息存储格式:topi ...

  10. 搞懂分布式技术28:微服务(Microservice)那点事

    搞懂分布式技术28:微服务(Microservice)那点事 微服务(Microservice)那点事 肥侠 2016-01-13 09:46:53 浏览58371 评论15 分布式系统与计算 微服务 ...

随机推荐

  1. HTML+CSS基础知识(6)背景的设置、表格的设计、表单的设计和框架集

    文章目录 1.背景 1.1 代码 1.2 测试结果 2.背景练习 2.1 代码 2.2 测试结果 3.表格 3.1 代码 3.2 测试结果 4.练习 4.1 代码 4.2 测试结果 5.表单 5.1 ...

  2. Go | 讲解GOROOT、GOPATH、GOBIN

    前言 Go(又称 Golang)是 Google 开发的一种静态强类型.编译型.并发型,并具有垃圾回收功能的编程语言.Go 被誉为是未来的服务器端编程语言. Go是一门全新的静态类型开发语言,具有自动 ...

  3. golang中的变量阴影

    索引:https://waterflow.link/articles/1666019023270 在 Go 中,在块中声明的变量名可以在内部块中重新声明. 这种称为变量阴影的原理很容易出现常见错误. ...

  4. 利用inotify和rsync服务实现数据实时同步

    文件定时同步的实现: 利用rsync结合cron计划任务实现: rsync -av --delete /data/ 10.0.0.12:/back -a:保留文件属性 -v:显示过程 -delete: ...

  5. CSS 属性选择器 ~=, |=, ^=, $=, *= 的区别

    CSS 属性选择器 ~=, |=, ^=, $=, *= 的区别 总结: "value 是完整单词" 类型的比较符号: ~=, |= "拼接字符串" 类型的比较 ...

  6. Java基础面试总结

    常见编译型语言:C.C++.Go.Rust 等(执行速度快,但开发效率低) 常见解释型语言:Python.JavaScript.PHP(开发效率高,但执行效率低) 先编译后解释:Java 重载和重写有 ...

  7. Arch Linux + KDE 配置&美化(持续更新~)

    Arch Linux + KDE 配置&美化(持续更新~) 这篇文章着重记录archlinux + KDE的一个基本的配置过程.不包括安装过程(使用archInstall.sh).内容大概有以 ...

  8. vulnhub靶场之DRIPPING BLUES: 1

    准备: 攻击机:虚拟机kali.本机win10. 靶机:DRIPPING BLUES: 1,网段地址我这里设置的桥接,所以与本机电脑在同一网段,下载地址:https://download.vulnhu ...

  9. (Java)设计模式:创建型

    前言 这篇内容是从另一篇:UML建模.设计原则 中分离出来的,原本这个创建型设计模式是和其放在一起的 但是:把这篇创建型设计模式放在一起让我贼别扭,看起来贼不舒服,越看念头越不通达,导致老衲躺在床上脑 ...

  10. linux mint 归档管理器报错Extraction not performd

    解决办法 后缀名的问题,后缀名与文件的真正类型不符合,至于到底是上面压缩类型,那只能靠尝试了,比如我这个是rar, 实际是zip,很坑,网上也没有这个问题的描述 其他 感觉 linux 对于文件类型方 ...