由于工做碰到了一些疑惑因此看了火狐的http文档, 简单地看, 简单地总结了一下, 本文只介绍http1.1的概念, 不介绍具体让人心烦的细节(配置和行为).css
全称是超文本传输协议. 何为超文本? 超文本就是文本(文本不必定是超文本).html
http的本体是文本. 而且http2以前的版本(包含如今正在用的1.1)都是人类可读的文本.web
再说一下什么是协议? 协议就是双方约定一些东西, 使用的时候你们都遵守规则执行.canvas
咱们来类比html, 超文本标记语言. 自己是文本(div, p, img). 放到浏览器里解析的时候就会被画成一个块, 一个图片等. 那么http也是如此, 普通的人类可读的文本, 进行了一系列约定, 协议双方根据一些关键词来执行某些约定的行为, 即是http了.api
那么http究竟是在哪里发生的, http的三个属性:跨域
高中就学过了osi七层协议, http是最上层的协议, 下面是基于传输层的(不只限于tcp/ip).浏览器
客户端指浏览器, 服务端指服务器. 顺序是浏览器的某些动做(好比输入url并敲回车)触发http请求, 服务器接到请求返回, 造成了一次完整的http请求. http请求每次都是独立的, 因此是无状态协议.缓存
http就是浏览器使用传输层协议向服务器发出一些文本, 这些文本带有约定的东西, 服务器根据约定的规则来分析内容并做出响应. 学习http就是学习这些约定.安全
就像html是div, p, img同样, http长啥样, 平时使用浏览器的调试工具或是http抓包工具都能看到. (固然都是进行过可视化处理的).服务器
http消息分为请求(request)消息和响应(response)消息. 即浏览器发出请求的消息和服务器响应的消息.
request和response的消息组成是同样的.
request和response的每一个部分的消息内容不一样. 下面介绍每一个部分的具体内容.
GET /background.png HTTP/1.1
body有两种状况: 单个资源: 此时header要定义content-type
和content-length
. 多个资源: 在content-type
里定义boundary
, 而后在body中用boundary
来分隔多个资源. 例子连接
HTTP/1.1 404 Not Found
.transfer-encoding
设为chunked
.至此, http已经介绍完了. 我来举一个简单的http的例子.
我打开了浏览器, 敲入yo-cwj.com
. 浏览器发出了http request.
GET https://yo-cwj.com HTTP/1.1 Host: yo-cwj.com User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive
这个简单的get请求没有body, header都是浏览器默认带上的.
而后收到了回复:
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2.0.61 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml <html>陈文俊的博客</html>
200, ok 表明请求成功, 倒数第二行空行表明header和body的分隔, 具体返回内容是<html>xxx</html>
, 浏览器得到结果就能够去渲染页面啦, 完美.
是的, http就是这么简单, http的结构就是start-line, header, body三部分. 而协议复杂的地方大部分就在header了. header有一万个字段, 每一个字段能研究一年. (因此要搞懂http须要一万年). 那么下面的章节简述一下常常接触的协议规则.
http是无状态协议, 但网站的登陆状态/购物车等是有状态的, 就要借助cookie来实现. cookie是储存在浏览器上的信息. 会在向服务器发起请求的时候带着, 以表明浏览器当前的状态.
cookie原先的做用除了登陆/购物车, 还有储存用户主题, 分析用户行为等. 但浏览器的行为会将cookie都带到http请求中, 因此如今推荐使用现代storage api来储存部分信息.
两个关键点: cookie传输是经过http的header, cookie的储存的地方是浏览器.
response header能够设置cookie:
Set-Cookie: <cookie-name>=<cookie-value>
而后浏览器收到set-cookie头之后会储存cookie, 在发送请求时把对应的cookie带在request header的Cookie
中, 格式是: k=v; k2=v2
:
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
那么浏览器中会有不少cookie, 由于咱们常常同时浏览不一样的网页. 浏览器进行request的时候把全部cookie带上是不对的, 那么会带上哪些cookie呢, 就涉及到cookie的做用范围.
控制cookie做用范围的关键字是Domain和Path, 若是都没设置默认行为是只向当前路由发送cookie, 个人理解是什么路由接到set-cookie的就只向这个路由发送.
domain和path的语法是Domain=mozilla.org
, Path=/docs
. domain被设置的时候会向domain的全部子domain发送, 因此但愿发送范围越小就要设置得越细. path相同.
cookie的生命周期是浏览器关闭, 也能够在response header里经过设置expire来改变cookie的过时时间.
由于浏览器经过document.cookie
能够获取本身的cookie. 经过一些手段发出一些请求并带上cookie就能够获取cookie来作很差的事情. 这也是http的特色: 无状态. 因此理论上一切请求都是能够模拟的. (只要获取了关键信息, 任何人均可以在他的电脑上模拟你正在登录某网上银行甚至进行操做).
这些操做有: 让页面执行一段js, 让页面append一个img, src的target是恶意网站. 因此防止xss攻击只要作到控制用户可进行的操做或转移用户输入就能够了.
题外话, 由于js和css和html都是明文的, 因此安全必须经过加密手段来强化.
跨域好像是每隔一段时间都会被问到的问题, 先来定义一下什么是跨域请求.
违反同源策略的请求就叫跨域. 同源策略一句话就能说完: 协议, 主机, 端口都相同的url是同源url. 强调是都相同, 即便http
和https
的区别也算跨域. 左边的连接举了一些例子, 一看就明白.
那么从一个页面向一个非同源的target发起了http请求, 这个请求就是跨域请求了.
那么什么状况下会发起跨域请求呢? 个人印象里百分之90的状况是js代码发起的, 也就是或通过框架包装的xmlhttprequest. 下面这些都会触发http请求:
@font-face
.drawImage
画的Image或者Video.说了半天什么状况是跨域, 那么为何要讨论跨域呢? 固然是报错了才会讨论了.
由于安全关系, http是默认阻止跨域请求的, 想要顺利地进行跨域请求, 必须在浏览器和服务器都进行一些header设置, 来确认此次跨域请求是双方都认同的. 就像你要删除社交工具的好友前会进行提示: 你是否要删除好友xxx.
跨域相关的request和response的header都在左边的连接里了, 这里只提一个做为例子:
(开始讲故事)
个人博客(https://yo-cwj.com)须要加载一... 由于博客托管的服务器对博客大小有限制, 因此我把图片放在了另一个图库(https://picture-cwj.com). (下文就用博客
和图库
来表明2个地址).
博客使用了img标签来请求了图库的图片. 图库返回的图片response header 带有:
Access-Control-Allow-Origin: https://yo-cwj.com
博客进行请求的request header带有:
Origin: https://yo-cwj.com
图库的response header告诉全部过来的请求: 我只给yo-cwj.com
跨域. 博客的request header带着代表身份的Origin
header. 这样一次不被阻止的跨域就完成了.
(故事完)
故事讲完了, 博客是存在的, picture-cwj.com是不存在的. 简单的2个header就让浏览器放行了跨域请求. 别的header都在故事前贴出来的连接中.
强行翻译: 跨域准备请求.
当跨域请求知足了某些条件之后, 浏览器在跨域请求前会发起一次preflight request, 用来确认即将发送的请求是否被容许.
preflight请求的method是options, 以前说的跨域相关的header大部分是和preflight相关的.
下面介绍发起preflight请求的触发条件:
get
, post
, head
的.cotent-type
头的值在指定范围以外的.只要知足任何一个条件就会发起preflight请求. 具体条件在左边的连接中.
关于缓存暂时只作概念介绍, 缓存的控制也都是header控制的.
什么是缓存? 当同一个请求进行了2次以上, 浏览器不真正向浏览器发起请求而直接返回以前储存的结果.
缓存的好处是: 提升浏览器响应速度, 节省服务器带宽. 由于没有与服务器真正数据交互, 也得到了指望里的数据.
缓存的问题也很是明显, 得到的数据是缓存里的, 而不是最新的. 因此缓存的关键就在于猜想哪些数据是不常常更新的. 猜想什么类型的数据的更新频率是多少, 并使用缓存相关的header来控制. 好比某门户网站的首页html是不常常更新的, 或者是每小时一更新, 而首页轮播的图片是十分钟更新的.
缓存类型分为本地缓存和共享缓存.
咱们概念中的, 或者说咱们常用的都是本地缓存.
共享缓存是指ISP对服务器的缓存, 以前据说淘宝怎么能让网速更快, 离用户最近的地方是ISP机房, 因此把淘宝首页放在ISP机房就好了.
有一种缓存的机制是新鲜度检查. 以前说的缓存response是: 200 OK (from disk cache). 新鲜度检查是根据cache-control: max-age=xxx
向服务器发起新鲜度检查. 若是返回结果是304(not modified), 服务器将不返回数据, 使用浏览器缓存的数据, 从而节省数据下载时间和带宽.