HTTP协议原理和深入

6次阅读

共计 6870 个字符,预计需要花费 18 分钟才能阅读完成。

前端面试常见问题:
http method

HTTP1.0 定义了三种请求方法:GET、POST 和 HEAD

HTTP1.1 新增了五种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE、CONNECT

http status code
2 开头(请求成功)表示成功处理了请求的状态代码。

200(成功)服务器已成功处理了请求。通常,这表示服务器提供了请求的网页。
201(已创建)请求成功并且服务器创建了新的资源。
202(已接受)服务器已接受请求,但尚未处理。
203(非授权信息)服务器已成功处理了请求,但返回的信息可能来自另一来源。
204(无内容)服务器成功处理了请求,但没有返回任何内容。
205(重置内容)服务器成功处理了请求,但没有返回任何内容。
206(部分内容)服务器成功处理了部分 GET 请求。

3 开头(请求被重定向)表示要完成请求,需要进一步操作。通常,这些状态代码用来重定向。

300(多种选择)针对请求,服务器可执行多种操作。服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
301(永久移动)请求的网页已永久移动到新位置。服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302(临时移动)服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
303(查看其他位置)请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
304(未修改)自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。
305(使用代理)请求者只能使用代理访问请求的网页。如果服务器返回此响应,还表示请求者应使用代理。
307(临时重定向)服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

4 开头(请求错误)这些状态代码表示请求可能出错,妨碍了服务器的处理。

400(错误请求)服务器不理解请求的语法。
401(未授权)请求要求身份验证。对于需要登录的网页,服务器可能返回此响应。
403(禁止)服务器拒绝请求。
404(未找到)服务器找不到请求的网页。
405(方法禁用)禁用请求中指定的方法。
406(不接受)无法使用请求的内容特性响应请求的网页。
407(需要代理授权)此状态代码与 401(未授权)类似,但指定请求者应当授权使用代理。
408(请求超时)服务器等候请求时发生超时。
409(冲突)服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息。
410(已删除)如果请求的资源已永久删除,服务器就会返回此响应。
411(需要有效长度)服务器不接受不含有效内容长度标头字段的请求。
412(未满足前提条件)服务器未满足请求者在请求中设置的其中一个前提条件。
413(请求实体过大)服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
414(请求的 URI 过长)请求的 URI(通常为网址)过长,服务器无法处理。
415(不支持的媒体类型)请求的格式不受请求页面的支持。
416(请求范围不符合要求)如果页面无法提供请求的范围,则服务器会返回此状态代码。
417(未满足期望值)服务器未满足 ” 期望 ” 请求标头字段的要求。

5 开头(服务器错误)这些状态代码表示服务器在尝试处理请求时发生内部错误。这些错误可能是服务器本身的错误,而不是请求出错。

500(服务器内部错误)服务器遇到错误,无法完成请求。
501(尚未实施)服务器不具备完成请求的功能。例如,服务器无法识别请求方法时可能会返回此代码。
502(错误网关)服务器作为网关或代理,从上游服务器收到无效响应。
503(服务不可用)服务器目前无法使用(由于超载或停机维护)。通常,这只是暂时状态。
504(网关超时)服务器作为网关或代理,但是没有及时从上游服务器收到请求。
505(HTTP 版本不受支持)服务器不支持请求中所用的 HTTP 协议版本。
缓存

客户端缓存
代理服务器缓存
缓存如何验证可用性

cache-control:

max-age=100 静态资源缓存 100s
public、private 设置只能在客户端缓存,还是可以通过代理服务器缓存
must-revalidate 在缓存过期后必须到服务器端验证过才能继续使用缓存
no-cache、no-store 控制是否使用缓存

缓存验证

last-modified 配合 if-modified-since

etage 配合 if-none-match

缓存是 web 开发中对性能提升最大的一面
更有意义的头部

Content-type、Content-Encoding 等用来约束数据类型

cookie 保持会话信息

CORS 实现跨域并保持安全性限制

深入到 TCP:

什么是三次握手
HTTPS 链接的创建过程,以及为什么 HTTPS 就是安全的
什么是长链接,为什么需要长链接
HTTP2 的信道复用为什么能提升性能

输入 URL 后 HTTP 请求返回的完整过程

1、为什么一开始需要做 redirect:因为浏览器可能记录了这个地址永久跳转成一个新的地址,一开始浏览器需要判断 redirect,redirect 到什么地址
2、看缓存:看请求的资源是否已经缓存
3、dns 解析
4、创建连接
5、开始发送数据包

Nginx

配置 ngnix 作为 http 的代理
开启 ngnix 的缓存功能
利用代理缓存提高 http 性能

HTTP 协议基础及发展历史
五层网络模型介绍

物理层:主要定义物理设备如何传输数据,硬件设备

数据链路层:在通信的实体间简历数据链路链接

网络层:为数据在节点之间传输创建逻辑链路

传输层:像用户提供可靠的端到端 (End-to-End) 服务传输层向高层屏蔽了下层数据通信的细节

应用层: 为应用软件提供了很多服务

构建于 TCP 协议之上屏蔽了网络传输相关细节

HTTP 协议发展历史
HTTP 0.9

1、只有一个命令 GET
2、没有 header 等描述数据的信息
3、服务器发送完毕,就关闭了 TCP 连接

HTTP1.0

1、增加了很多命令
2、增加 status code 和 header
3、多字符集支持、多部分发送、权限、缓存等

HTTP1.1

1、持久连接(建立 TCP 消耗)
2、pipeline(同一个链接可以发送多个请求,服务端是按照顺序接受,可能需要等待,串行)
3、增加 host 和其他一些命令

HTTP2(尚未普及)1、所有数据以二进制进行传输 2、同一个链接里面发送多个请求不再小按照顺序来(并行)3、头信息压缩以及推送等提高效率的功能
HTTP 的三次握手

客户端和服务器端进行信息发送,是需要创建一个 TCP-connetion
http 是不存在连接这个概念,只有请求和响应,它们都是数据包
tcp 链接可以发送多个 http 请求

URI-URL 和 URN
Uniform Resource Locator/ 统一资源定位器
http://user:pass@host.com:80/path?query=string#hash
URN: 永久统一资源定位符

在资源移动之后还能找到
目前还没有非常成熟的使用方案

HTTP 报文格式

HTTP 各种特性总览
认识 http 客户端
curl -v www.baidu.com
CORS 跨域请求的限制与解决
请求已经发送,已经获取到了返回数据。不过浏览器在解析返回的时候,发现是不允许的,浏览器拦截了,隐藏了数据。必须服务器允许跨越请求。
浏览器允许 link、script、img 这些在标签上写路径加载的时候,允许跨越,不管服务器是否允许跨域请求。jsnop 原理也是如此
服务器端可以加:’Access-Control-Allow-Origin’: ”,表示允许跨域访问。” 表示允许所有跨域访问,可以设置指定的服务器访问。多域可以动态判断
### CORS 跨域限制以及预请求验证

> 不需要预请求的限制:

– 1、允许 method:
GET、HEAD、POST
– 2、允许 Content-Type:
text/plain、
multipart/form-data、
application/x-www-form-urlencoded
– 3、请求头限制:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:
只限于三个值 application/x-www-form-urlencoded、
multipart/form-data、
text/plain
– 4、XMLHttpRequestUpload 对象军没有注册任何事件监听器
– 5、请求中没有使用 ReadableStream

> 解决方法:

‘Access-Control-Allow-Origin’: ‘http://127.0.0.1:8888′,’Access-Control-Allow-Headers’: ‘X-Test-Cors’,’Access-Control-Allow-Methods’: ‘POST, PUT, DELETE’,
‘Access-Control-Max-Age’: ‘1000’// 允许以这种方式发送预请求的时间,这段时间内不需要再发送预请求了

### 缓存头 Cache-Control 的含义和使用
> 可缓存性
– pulic :http 请求经过的任何路径都可以对返回内容的缓存
– private: 只有发起请求的浏览器才可以进行缓存
– non-cache: 任何节点都不可以进行缓存

> 到期:
– max-age=<seconds>
– s-maxage=<seconds> // 如果两个都设置,代理服务器会读取
– max-stale=<seconds> // 只有在发起端设置才管用,即便 max-age 过期,只要在 max-stale 时间内仍然可以使用过期的缓存,服务端返回中设置没有作用

> 重新验证:

– 1、must-revalidate// 设置了 max-age 中如果已经过期了,必须去原服务端重新发送请求,重新获取数据验证是否真的过期
– 2、proxy-revalidate// 缓存服务器中
– 3、no-store// 永远都要去服务器拿新的
– 4、no-transform// 告诉代理服务器不可改动内容

> cache-control 应用
– 1、只是声明性的,并没有强制约束力
– 2、chrome 里面的 disable cache 必须勾掉
– 3、cache-control 是一种客户端缓存,而且一般缓存时间都比较长,可能会导致服务端静态资源改变而客户端无法更新。解决方案:在静态资源文件后面加上一串哈希码,如果内容没有变,哈希码没变,可以使用静态资源缓存;如果文件有边,发的请求就是新的静态资源请求。

‘Cache-Control’: ‘max-age=200,public’
缓存验证 Last-Modefied 和 Etag 的使用
资源验证

last-modified

上次修改时间
配合 If-Modified-Since 或者 If-Unmodified-Since 使用

Etag
更加严格的验证
数据签名(任何的修改,唯一),最典型的就是哈希计算得到唯一值
配合 If-Match 或者 If-Non-Match
对比资源的签名判断是否使用缓存
1、304:Not Modified。资源没有修改,可以直接读缓存。会忽略 response body 里面的内容。
2、If-Modified-since 和 If-None-Match,disable cache 缓存验证头就不发送这两个参数。
3、如果设置了 no-store 会忽略所有跟缓存有关的
const http = require(‘http’)
const fs = require(‘fs’)

http.createServer(function(request, response) {
console.log(‘request ‘, request.url)
const html = fs.readFileSync(‘test.html’, ‘utf8’)
if (request.url === ‘/’) {
const html = fs.readFileSync(‘test.html’, ‘utf8’)
response.writeHead(200, {
‘Content-Type’: ‘text/html’
})
response.end(html)
}
if (request.url === ‘/script.js’) {
const html = fs.readFileSync(‘test.html’, ‘utf8’)

const etag = request.headers[‘if-none-match’]
if (request.getHeader = ‘777’) {
response.writeHead(304, {
‘Content-Type’: ‘text/javascript’,
‘Cache-Control’: ‘max-age=2000000,no-cache’,
‘Last-Modified’: ‘123’,
‘Etag’: ‘777’
})
response.end(‘123’)
} else {
response.writeHead(200, {
‘Content-Type’: ‘text/javascript’,
‘Cache-Control’: ‘max-age=2000000,no-cache’,
‘Last-Modified’: ‘123’,
‘Etag’: ‘777’
})
response.end(‘console.log(“script loadded”)’)
}
}
}).listen(8888)

console.log(‘serve listening on 8888’)
const http = require(‘http’)
const fs = require(‘fs’)

http.createServer(function(request, response) {
console.log(‘request ‘, request.url)
const html = fs.readFileSync(‘test.html’, ‘utf8’)
response.writeHead(200, {
‘Access-Control-Allow-Origin’: ‘*’,
‘Access-Control-Allow-Headers’: ‘X-Test-Cors’

})
response.end(html)
}).listen(8887)

console.log(‘serve listening on 8887’)
cookie 和 session
cookie

通过 Set-Cookie 设置,同域请求中
下次请求会自动带上
键值对,可以设置多个

cookie 属性

max-age 和 expires 设置过期时间
secure 只在 https 的时候发送
httpOnly 无法通过 document.cookie 访问

‘Set-Cookie’:[‘id=12343′,’max-age=10′,’name=dafdafda’;HttpOnly]
不同域 cookie 不能获取,同一个主域名的二级域名可以共享 cookie。
HTTP 长连接

复用 TCP/IP 连接
三次握手的开销可能不要比长连接消耗的高
Connection: keep-alive
chrome 一般六个并发
HTTP2 信道复用

数据协商
请求

Accept:// 返回数据类型
Accept-Encoding:// 主要是如何数据压缩
Accept-Language:// 返回语言
User-Agent:// 返回 pc 端还是移动端

返回
Content-Type:对应 Accept
Content-Encoding: 对应 Accept-Encoding
Content-Language: 对应 Accept-Language
X-Content-Type-Options:nosniff // 不会主动预测返回内容
数据压缩
const zlib = require(‘zlib’)
‘Content-Encoding’:’gzip’
Redirect
301 Moved Permanently 被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。重定向在浏览器缓存中,如果用户不清理缓存,那么服务端没法控制 302 Found 请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在 Cache-Control 或 Expires 中进行了指定的情况下,这个响应才是可缓存的。

CSP 内容安全策略
CSP 定义了 Content-Security-PolicyHTTP 头来允许你创建一个可信来源的白名单,使得浏览器只执行和渲染来自这些来源的资源,而不是盲目信任服务器提供的所有内容。即使攻击者可以找到漏洞来注入脚本,但是因为来源不包含在白名单里,因此将不会被执行。
作用

限制资源获取
报告资源获取越权

限制方式

default-src 限制全局
制定资源类型

Nginx 代理以及面向未来的 HTTP

正文完
 0