网络协议分层
物理层:定义物理设备如何去传输设备
数据链路层:在通信实体之间建立数据链路连接
网络层:为数据在结点之间传输创建逻辑链路
传输层:向用户提供端到端的服务(tcp,udp),传输层向高层屏蔽 了下层数据通信的细节
应用层:为应用软件提供了很多服务,构建于tcp协议之上,屏蔽了网络传输的相关细节
HTTP历史
HTTP/0.9 只有GET,没有header等描述数据的信息,服务器发送完毕就关闭tcp连接。
HTTP/1.0 增加了很多命令,增加了status code和header,增加了多字符集支持、多部分发送、权限、缓存。
HTTP/1.1 支持了持久连接,增加了pipeline在同一个连接里发送多个请求,增加了host和其他命令。
HTTP/2.0 所以的数据以二进制传输,同一个连接里面发送的请求不需要再按照顺序来,头信息压缩及推送等提高效率的功能
HTTP三次握手
URI,URL,URN
URI:Uniform Resource Identifier统一资源标识符,用来位移标识互联网上的信息资源,包括URL和URN
URL:Uniform Resource Locator统一资源定位器
URN:Uniform Resource Name永久同一资源定位符,在资源移动之后还可以被找到,目前还没有非常成熟的方案
HTTP报文
HTTP方法
用来定义对于资源的操作
常用的有GET和POST等
从定义上讲有各自的语义
HTTP CODE
定义服务器对请求的处理结果
各个区间的CODE有各自的语义
好的HTTP服务可以通过CODE判断结果
一个最简单的web服务
const http = require('http');
http.createServer(function(request,response){
console.log('request come',request.url);
response.end('1234');
}).listen(8888);
console.log('server listening on 8888');
CORS跨域请求
response.writeHead(200,{
'Access-Control-Allow-Origin':'*'
})
在要访问的服务器上加上这个头就可以跨域了
<script src='http://127.0.0.1:8887/'></script>
也可以用jsonp的方式,浏览器允许link、img、script标签跨域
CORS的预请求
允许的方法,即不需要预请求
GET
HEAD
POST
允许的Content-Type,即不需要预请求
text/plain
multipart/form-data
application/x-www-form-urlencoded
其他限制
请求头限制
XMLHttpRequestUpload对象均没有注册任何时间监听器
请求中没有使用ReadableStream对象
预请求方法
Request Method: OPTIONS
预请求是method会变成OPTIONS
'Access-Control-Allow-Headers':'X-Test-Cors'
在访问的服务器端设置自定义的头
'Access-Control-Allow-Methods':'POST,PUT,DELETE'
在访问的服务器端设置允许的方法
'Access-Control-Max-Age':'1000'
允许允许跨域请求的最长时间,1000s内不需要再预请求
Cache-Control
可缓存性
- public:http经过的任何节点都可以进行缓存
- private:发起请求的浏览器可以缓存
- no-cache:任何一个节点都不可以缓存,本地可以有缓存,但要等到服务器验证之后才可以使用
到期
- max-age=<seconds>:设置缓存内容多少秒之后过期
- s-maxage=<seconds>:代替max-age,只有在代理服务器中才有效
- max-stale=<seconds>:在max-age过期之后,如果返回的资源有max-stale的设置,表示即便缓存已经过期了,但是在max-stale的期限之内还是可以使用过期的缓存,不需要再从服务器获取
重新验证
- must-revalidate:在设置的max-age的缓存当中,如果已经过期了,必须去原服务器发送请求重新获取数据,再来验证本地缓存是否真正过期,不能直接使用本地的缓存
- proxy-revalidate:使用在代理服务器中
其他
- no-store:彻底的本地和代理服务器都不可以由缓存,永远都要从服务器中区
- no-transform:用在代理服务器端,告诉代理服务区不要随便改动返回的内容
资源验证
验证头
Last-Modified:上次修改时间,配合If-Modified-Since或者If-Unmodified-Since使用,对比上次修改时间来验证资源是否需要更新
Etag:数据签名,配合If-Match或If-Non-Match,对比资源的签名判断是否使用缓存
Cookie
通过Set-Cookie设置,下次请求会自动带上,键值对保存,可以设置多个
属性
max-age和expires设置过期的时间
Secure只在https的时候发送
HttpOnly无法通过document.cookie访问,安全性好
'Set-Cookie':['id=123;max-age=2','abc=456;HttpOnly']
HTTP长连接
'Connection':'keep-alive'
默认是close
数据协商
请求
Accept:想要的数据类型
Accept-Encoding:限制服务端如何进行数据压缩
Accept-Language:限制语言
User-Agent:浏览器信息
返回
Content-Type:
Content-Encoding:
Content-Language:
Redirect
response.writeHead(302,{
'Location':'/new'
})
302表示临时跳转,每次都要经过服务端的跳转。301表示永久跳转,只有第一次需要服务器的跳转,之后就永久跳转,每次都是从缓存里跳转,这样会有麻烦。用户主动清理浏览器的换成才能解决。
CSP Content-Security-Policy内容安全策略
作用
- 限制资源的获取:从哪里获取,请求发送到哪里
- 报告资源获取越权
限制方式
- default-src限制全局
- 制定资源类型,connect-src、img-src、media-src、script-src、style-scr
'Content-Security-Policy':'default-src http: https:'
限制只能通过http或者https的方式加载,不能写在html里面
'Content-Security-Policy':'default-src \'self\''
只能加载本站提供的外链脚本
'Content-Security-Policy':'default-src \'self\' https://cdn.bootcss.com'
允许加载此域名下的脚本
'Content-Security-Policy':'default-src \'self\' https://cdn.bootcss.com; report-uri /report'
发送了report请求,内容是csp-report的内容
'Content-Security-Policy-Peport-Only':'default-src \'self\' https://cdn.bootcss.com; report-uri /report'
检测到资源不像加载,但不会强制他不加载,正常加载并做一个report的工作
Nginx
代理
启动nginx,到nginx的目录下./nginx.exe
配置nginx.conf文件,最好是从外部引入,方便操作include servers/*.conf
将配置文件引入到nginx.conf中
设置test.conf文件
server {
listen 80;
server_name www.abc.com;
location / {
proxy_pass http://127.0.0.1:8887;
proxy_set_header Host $host;
}
}
server_name
表示的在浏览器访问的hostname,根据这个hostname判断将服务代理到哪里
在这里遇到一个问题,当访问www.abc.com
的时候出现问题访问不了,这是因为没有修改本地ip地址映射,在C:\Windows\System32\drivers\etc\hosts
修改hosts文件,添加一行127.0.0.1 www.abc.com
,就可以访问了
proxy_set_header Host $host;
设置请求的头部,如果不设置那么request.headers.host是127.0.0.1:8887
,如果设置了就是www.abc.com
缓存
proxy_cache_path cache levels=1:2 keys_zone=my_cache:10m
proxy_cache_path
来配置一个缓存
cache levels=1:2
保存在cache文件夹中,并且有二级文件夹
keys_zone=my_cache:10m
声明一个10m的缓存,名字是my_cache
location / {
proxy_cache my_cache;
proxy_pass http://127.0.0.1:8887;
proxy_set_header Host $host;
}
const http = require('http');
const fs = require('fs');
const wait = (seconds) => {
return new Promise((resolve,reject) => {
setTimeout(()=>{
resolve()
},seconds*1000)
})
}
http.createServer(function(request,response){
console.log('request come',request.headers.host);
const html = fs.readFileSync('test.html','utf-8');
if(request.url==='/'){
response.writeHead(200,{
'Content-Type':'text/html'
})
response.end(html);
}
if(request.url==='/data'){
response.writeHead(200,{
'Cache-Control':'max-age=20, s-maxage=20, private'
})
wait(2).then(() => response.end('success'))
}
}).listen(8887);
console.log=('server listening on 8887');
设置了代理缓存,那么在
max-age
期限之内,再换一个浏览器打开网页,缓存还是存在的
如果同时设置了max-age
和s-maxage
那么代理缓存会使用s-maxage
private
表示只有浏览器可以缓存现有的数据,代理是不可以缓存的,代理服务器不会生效.no-store
表示所有的地方都不缓存
代理缓存对通用缓存来说更高效
HTTPS
HTTP是明文传输的,可以被拦截,可以被读取,相当于裸奔
加密
私钥
只放在服务器上
公钥
需要私钥才能解密
Nginx部署HTTPS
密钥生成地址
https://gist.github.com/Jokcy/5e73fd6b2a9b21c142ba2b1995150808
密钥生成命令
openssl req -x509 -newkey rsa:2048 -nodes -sha256 -keyout localhost-privkey.pem -out localhost-cert.pem
在nginx
的执行目录里新建一个certs
文件夹,执行上面的命令,会出现两个文件localhost-privkey.pem
和 localhost-cert.pem
在test.conf
里配置
proxy_cache_path cache levels=1:2 keys_zone=my_cache:10m;
server {
server_name www.abc.com;
listen 443 ssl;
ssl_certificate_key ../certs/localhost-privkey.pem;
ssl_certificate ../certs/localhost-cert.pem;
location / {
proxy_cache my_cache;
proxy_pass http://127.0.0.1:8887;
proxy_set_header Host $host;
}
}
然后访问
https://www.abc.com
,注意http
的端口是443
配置当访问http的时候自动访问https
在 test.conf中添加一个server
server{
listen 80 default_server;
listen [::]:80 default_server;
server_name www.abc.com;
return 302 https://$server_name$request_uri;
}
HTTP2
优势
- 信道复用
- 分帧传输,每一帧都有上下文联系,不一定要连续发送,把数据传送完毕后,根据帧信息的先后顺序进行组合,拿到数据。可以在同一个连接上并发的发送不同的请求。
- Server Push,服务端可以向用户端推送一些服务
Link在HTTP2中表示这个请求可以推送哪些内容
'Link':'</test.jpg>; as=image; rel=preload'
在test.conf中设置
proxy_cache_path cache levels=1:2 keys_zone=my_cache:10m;
server{
listen 80 default_server;
listen [::]:80 default_server;
server_name www.abc.com;
return 302 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name www.abc.com;
http2_push_preload on;
ssl_certificate_key ../certs/localhost-privkey.pem;
ssl_certificate ../certs/localhost-cert.pem;
location / {
proxy_cache my_cache;
proxy_pass http://127.0.0.1:8887;
proxy_set_header Host $host;
}
}
listen 443 ssl http2
http2是基于https的
http2_push_preload on
实现http2的server push的功能,根据Link
里的内容进行推送
chrome浏览器看不到push的内容,可以到chrome"//net-internals
查看