http1.1科普

由于工做碰到了一些疑惑因此看了火狐的http文档, 简单地看, 简单地总结了一下, 本文只介绍http1.1的概念, 不介绍具体让人心烦的细节(配置和行为).css

什么是http

概念

全称是超文本传输协议. 何为超文本? 超文本就是文本(文本不必定是超文本).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就是学习这些约定.安全

http消息

就像html是div, p, img同样, http长啥样, 平时使用浏览器的调试工具或是http抓包工具都能看到. (固然都是进行过可视化处理的).服务器

http消息分为请求(request)消息和响应(response)消息. 即浏览器发出请求的消息和服务器响应的消息.

消息组成

request和response的消息组成是同样的.

  1. start-line: 请求/响应的基本信息.
  2. http header: 请求/响应的头信息.
  3. 空行: 做为分隔符.
  4. body: 请求/响应的主体内容.

request和response的每一个部分的消息内容不一样. 下面介绍每一个部分的具体内容.

request

  1. start-line: 方法(get/post等), 目标(一般是url), 协议版本. 例: GET /background.png HTTP/1.1
  2. header, 用冒号/换行隔开的键值对, request和response拥有不一样的有效header键值, 详见文末连接.
  3. 大多数request的body为空, 好比get, delete, options方法. 一些须要上传数据的方法如post, put会有body.

    body有两种状况: 单个资源: 此时header要定义content-typecontent-length. 多个资源: 在content-type里定义boundary, 而后在body中用boundary来分隔多个资源. 例子连接

response

  1. start-line: 协议版本, 状态码, 状态描述. 例: HTTP/1.1 404 Not Found.
  2. header, 同request.
  3. response的body也不是必须的, 与request相似, 也分为单个资源和多个资源. 多了一个状况, 不知道文件长度的时候能够把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须要一万年). 那么下面的章节简述一下常常接触的协议规则.

Cookie

介绍

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的过时时间.

xss与csrf

由于浏览器经过document.cookie能够获取本身的cookie. 经过一些手段发出一些请求并带上cookie就能够获取cookie来作很差的事情. 这也是http的特色: 无状态. 因此理论上一切请求都是能够模拟的. (只要获取了关键信息, 任何人均可以在他的电脑上模拟你正在登录某网上银行甚至进行操做).

这些操做有: 让页面执行一段js, 让页面append一个img, src的target是恶意网站. 因此防止xss攻击只要作到控制用户可进行的操做或转移用户输入就能够了.

题外话, 由于js和css和html都是明文的, 因此安全必须经过加密手段来强化.

跨域请求

跨域好像是每隔一段时间都会被问到的问题, 先来定义一下什么是跨域请求.

定义

违反同源策略的请求就叫跨域. 同源策略一句话就能说完: 协议, 主机, 端口都相同的url是同源url. 强调是相同, 即便httphttps的区别也算跨域. 左边的连接举了一些例子, 一看就明白.

那么从一个页面向一个非同源的target发起了http请求, 这个请求就是跨域请求了.

触发对象

那么什么状况下会发起跨域请求呢? 个人印象里百分之90的状况是js代码发起的, 也就是或通过框架包装的xmlhttprequest. 下面这些都会触发http请求:

  • js代码发起的, xmlhttprequest, fetch. 由于fetch存在兼容问题, 基本全部的框架封装都是经过前者的.
  • web字体. 经过@font-face.
  • webgl texture.
  • canvas用drawImage画的Image或者Video.
  • css和script标签.

跨域请求须要作的事情

说了半天什么状况是跨域, 那么为何要讨论跨域呢? 固然是报错了才会讨论了.

由于安全关系, 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 request, 用来确认即将发送的请求是否被容许.

preflight请求的method是options, 以前说的跨域相关的header大部分是和preflight相关的.

下面介绍发起preflight请求的触发条件:

  1. method不是get, post, head的.
  2. request header 带有指定字段以外的.
  3. cotent-type头的值在指定范围以外的.

只要知足任何一个条件就会发起preflight请求. 具体条件在左边的连接中.

缓存

关于缓存暂时只作概念介绍, 缓存的控制也都是header控制的.

概念

什么是缓存? 当同一个请求进行了2次以上, 浏览器不真正向浏览器发起请求而直接返回以前储存的结果.

缓存哲学

缓存的好处是: 提升浏览器响应速度, 节省服务器带宽. 由于没有与服务器真正数据交互, 也得到了指望里的数据.

缓存的问题也很是明显, 得到的数据是缓存里的, 而不是最新的. 因此缓存的关键就在于猜想哪些数据是不常常更新的. 猜想什么类型的数据的更新频率是多少, 并使用缓存相关的header来控制. 好比某门户网站的首页html是不常常更新的, 或者是每小时一更新, 而首页轮播的图片是十分钟更新的.

缓存类型

缓存类型分为本地缓存和共享缓存.

咱们概念中的, 或者说咱们常用的都是本地缓存.

共享缓存是指ISP对服务器的缓存, 以前据说淘宝怎么能让网速更快, 离用户最近的地方是ISP机房, 因此把淘宝首页放在ISP机房就好了.

新鲜度检查

有一种缓存的机制是新鲜度检查. 以前说的缓存response是: 200 OK (from disk cache). 新鲜度检查是根据cache-control: max-age=xxx向服务器发起新鲜度检查. 若是返回结果是304(not modified), 服务器将不返回数据, 使用浏览器缓存的数据, 从而节省数据下载时间和带宽.

参考连接

原文地址

相关文章
相关标签/搜索