开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情
Http 相关-代理、缓存、跨域
Http
结构:起始行 + 头部 + 空行 + 实体 请求报文:GET /home HTTP/1.1 也就是方法 + 路径 + http 版本 响应报文:HTTP/1.1 200 OK 响应报文的起始行也叫做 状态行 。由 http 版本、状态码和原因三部分组成
http 是可靠传输。HTTP 基于 TCP/IP,因此把这一特性继承了下来。这属于 TCP 的特性 无状态。这里的状态是指通信过程的上下文信息,而每次 http 请求都是独立、无关的,默认不需要保留状态信息 http 协议里的报文(主要指的是头部)不使用二进制数据,而是文本形式。
对于定长包体而言,发送端在传输的时候一般会带上 Content-Length , 来指明包体的长度。 当长度小于时会被截取掉,当长度设置过大时会直接报服务器异常,无法访问
对于不定长包体,使用 Transfer-Encoding: chunked 表示分块传输数据,设置这个字段后会自动产生两个效果: Content-Length 字段会被忽略,基于长连接持续推送动态内容
http 处理表单提交数据 1、application/x-www-form-urlencoded 2、multipart/form-data
对于 格式的表单内容,有以下特点: 其中的数据会被编码成以 & 分隔的键值对 字符以 URL 编码方式编码。
格式最大的特点在于:每一个表单元素都是独立的资源表述。另 外,你可能在写业务的过程中,并没有注意到其中还有的存在,如果你打开抓包工具,确实可以看到不同的表单元素被拆分开了,之所以在平时感觉不到,是以为浏览器和 HTTP 给你封装了这一系列操作。 在实际的场景中,对于图片等文件的上传,基本采用 multipart/form-data 而不用 application/x-www-form-urlencoded 因为没有必要做 URL 编码,带来巨大耗时的同时也占用了更多的空间。
http 队头阻塞
HTTP 传输是基于请求-应答 的模式进行的,报文必须是一发一收,但值得注意的是,里面的任务被放在 一个任务队列中串行执行,一旦队首的请求处理太慢,就会阻塞后面请求的处理。这就是著名的队头阻塞问题。
解决 并发连接:对于一个域名允许分配多个长连接,那么相当于增加了任务队列,不至于一个队伍的任务阻塞其它所有任务。在 RFC2616 规定过客户端最多并发 2 个连接,不过事实上在现在的浏览器标准中,这个上限要多很多,Chrome 中是 6 个。 域名分片 分出非常多的二级域名,而它们都指向同样的一台服务器,能够并发的长连接数更多了,事实上也更好地解决了队头阻塞的问题。
http 缓存
首先通过 Cache-Control 验证强缓存是否可用 如果强缓存可用,直接使用 否则进入协商缓存,即发送 HTTP 请求,服务器通过请求头中的 If-Modified-Since 或者 If-None-Match 这些条件请求字段检查资源是否更新,若资源更新,返回资源和 200 状态码 否则,返回 304,告诉浏览器直接从缓存获取资源
CORS
CORS 其实是 W3C 的一个标准,全称是 跨域资源共享 。它需要浏览器和服务器的共同支持,具体来说, 非 IE 和 IE10 以上支持 CORS,服务器需要附加特定的响应头,后面具体拆解。不过在弄清楚 CORS 的原 理之前,我们需要清楚两个概念: 简单请求和非简单请求。
简单请求 请求方法为 GET、POST 或者 HEAD 请求头的取值范围: Accept、Accept-Language、Content-Language、Content-Type(只限于三个 值 application/x-www-form-urlencoded 、 multipart/form-data 、 text/plain )
请求发出去之前,浏览器做了什么? 它会自动在请求头当中,添加一个 Origin 字段,用来说明请求来自哪个 源 。服务器拿到请求之后,在 回应时对应地添加 Access-Control-Allow-Origin 字段,如果 Origin 不在这个字段的范围中,那么浏览器就会将响应拦截。 因此, Access-Control-Allow-Origin 字段是服务器用来决定浏览器是否拦截这个响应,这是必需的字 段。与此同时,其它一些可选的功能性的字段,用来描述如果不会拦截,这些字段将会发挥各自的作 用。
非简单请求
非简单请求相对而言会有些不同,体现在两个方面: 预检请求和响应字段。 我们以 PUT 方法为例。
预检请求的方法是 OPTIONS ,同时会加上 Origin 源地址和 Host 目标地址,这很简单。同时也会加上两 个关键的字段:
Access-Control-Request-Method, 列出 CORS 请求用到哪个 HTTP 方法 Access-Control-Request-Headers,指定 CORS 请求将要加上什么请求头
在预检请求的响应返回后,如果请求不满足响应头的条件,则触发 XMLHttpRequest 的 onerror 方法, 当然后面真正的 CORS 请求也不会发出去了。
CORS 请求的响应。绕了这么一大转,到了真正的 CORS 请求就容易多了,现在它和简单请求的情况是 一样的。浏览器自动加上 Origin 字段,服务端响应头返回 Access-Control-Allow-Origin。可以参考以 上简单请求部分的内容。
jsonp
JSONP 是 JSON with padding(填充式 JSON 或参数式 JSON)的简写。
JSONP 实现跨域请求的原理简单的说,就是动态创建<script>
标签,然后利用<script>
的 src 不受同源策略约束来跨域获取数据。
JSONP 由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的 JSON 数据。
var script = document.createElement("script");
script.src = "https://api.douban.com/v2/book/search?q=javascript&count=1&callback=handleResponse";
document.body.insertBefore(script, document.body.firstChild);
2、使用 jquery 封装 jsonp
$.ajax({
async : true,
url : "https://api.douban.com/v2/book/search",
type : "GET",
dataType : "jsonp", // 返回的数据类型,设置为 JSONP 方式
jsonp : 'callback', //指定一个查询参数名称来覆盖默认的 jsonp 回调参数名 callback
jsonpCallback: 'handleResponse', //设置回调函数名
data : {
q : "javascript",
count : 1
},
success: function(response, status, xhr){
console.log('状态为:' + status + ',状态是:' + xhr.statusText);
console.log(response);
}
});
通过$.getJSON()
利用 getJSON 来实现,只要在地址中加上 callback=?参数即可,参考代码如下:
$.getJSON("https://api.douban.com/v2/book/search?q=javascript&count=1&callback=?", function(data){
console.log(data);
});
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情