skip to content
天真笔录

HTTP笔记

/ 7 min read

HTTP发展历史

HTTP0.9

  1. 只支持GET
  2. 通信协议纯文本

HTTP1.0

  1. 增加HEAD、POST等新方法
  2. 增加响应状态码,标记可能错误原因
  3. 引入协议版本号概念
  4. 引入了HTTP Header(头部)概念,让HTTP处理响应和请求更加方便
  5. 传输数据不再仅限于文本

HTTP1.1

  1. 增加PUT、DELETE 等新方法
  2. 增加了缓存控制和管理
  3. 明确了连接管理,允许持久连接
  4. 允许响应数据分块,利于大文件传输
  5. 强制要求HOST头

HTTP2.0

  1. 二进制协议,不再是文本
  2. 可以发起多个请求,废弃了1.1里的管道
  3. 使用专用算法压缩头部,减少数据量传输
  4. 允许服务器主动向客户端推送数据
  5. 增强了安全性,“事实上”要求通信加密

URL

  1. Uniform Resource Locator(统一资源定位符)
  2. 组成:http://user:pass@hotst.com:80/path?query=string#hash
  • http: // 协议,如http、ftp、file
  • user:pass // 极少使用,可以忽略
  • host.com // 域名,会经DNS解析成IP,IP就是请求资源的服务器地址
  • 80 // 端口号,默认端口号80
  • path // 路由
  • query // 参数
  • #hash // #后面跟的是hash

http组成

请求

  • 请求行
  • 首部
  • 实体

响应

  • 状态行
  • 首部
  • 实体

跨域

跨域产生的条件

协议、端口号、域名之中有任一不同,即产生跨域

设置了Access-Control-Allow-Origin: * 就可以解决跨域了?

简单请求下是可以的,非简单请求则不行

简单请求

请求方法

  1. GET
  2. POST
  3. HEAD

请求头

  1. Accept
  2. Accept-Language
  3. Content-Language
  4. Content-Type: text/plain, multipart/form-data, application/x-wwww-form-urlencoded
  5. Last-Event-ID

    同时满足以上两种情况就是简单请求,否则非简单请求

非简单请求

请求方法

  1. PUT
  2. DELETE
  3. Content-Type: application/json
  4. 自定义请求头header如X-Tianzhen: 1

非简单请求会发起预请求options,检测是否支持跨域, 设置跨域时间 Access-Control-Max-Age:600单位:s,上限:2h,浏览器实现不一致

域名如何设置多个

Access-Control-Allow-Origin: *有安全问题,那么可以设置域名,但域名只能设置一个,针对需要多个跨域的域名如何设置?

服务端配置域名列表,动态条件设置

缓存

Expires(强缓存)

expires: 2022-2-2。缺点:返回的是服务器时间,比较的是客户端时间,可能不一致

Cache-Control

可缓存性

  1. public:任何都放都可以缓存
  2. private:只能在发起的浏览器缓存
  3. no-cache:允许缓存,但每次都需要到服务器验证后才能使用

缓存时间

  1. max-age: seconds 多少秒后过期(强缓存),时间计算起点是报文生成时间(Date字段)
  2. s-maxage: seconds 优先级更高,作用于代理服务器设置
  3. max-stale: seconds 发起方设置了此信息头,表示在max-age过期之后seconds秒内还可以使用过期的缓存,浏览器中无效,因为浏览器不会主动设置此头

重新验证

  1. must-revalidate max-age到期之后,必须去源服务端发送请求验证是否过期
  2. proxy-revalidate 与max-revalidate相似,指缓存服务器
其他
  • no-store 不使用缓存,即使设置了max-age
  • no-transform 告诉代理服务器不要使用转换(如:压缩)

缓存验证

Last-Modified

与浏览器携带If-Modified-Since或If-Unmodified-Since对比,来验证资源是否需要更新

Etag(数据签名)

与浏览器携带If-Match或这If-Non-Match比对,对比资源签名是否需要更新

Last-Modified和Max-Age的局限性

  • 对于模板渲染的页面,每次重新渲染之后会使Last-Modified失效,而Max-Age无法精确控制,这种场景Etag就更合适
  • Nginx -> Etag: on

见Cookie-Session-Token

数据协商

请求Accept

  1. Accept:
  2. Accept-Encoding
  3. Accept-Language
  4. User-Agent

响应Content

  1. Content-type
  2. Content-Language
  3. Content-Encoding

Redirect

  1. 301(永久重定向),Location: url 缓存在客户端,除非手动清除
  2. 302(临时重定向), Location: url

CSP(内容安全策略)

  • 对资源类型的加载做限制
  1. default-src::全局,对表单提交无效
  2. connect-src
  3. font-src
  4. style-src
  5. script-src
  6. media-src
  7. img-src
  8. manifest-src
  9. frame-src
  10. report-uri:报告资源获取越权
res.set("Content-Security-Policy", "default-src 'self'"); // 只允许本站的资源
res.set("Content-Security-Policy", "default-src 'self' https://cdn.bootcdn.net"); // 只允许本站的资源
res.set("Content-Security-Policy", "form-action 'self'; report-uri /report"); // 资源获取越权报告

Nginx代理

Host

server {
  listen 80;
  server_name node.tzhen.vip;
  location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host; // 不设置的话获取host与浏览器显示的host不一致
  }
}

代理缓存

proxy_cache_path cache levels=1:2 keys_zone=node_cache:10m;

server {
  listen 80;
  server_name node.tzhen.vip;
  location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_set_header Host $host;
    proxy_cache node_cache;
  }
}

代理缓存的意义:当用户访问过后,其他用户再访问时则会直接命中代理缓存,提高访问速度

s-max-age

res.set("Cache-Control", "max-age=2, s-maxage=20");
  • max-age:浏览器使用
  • s-maxage:代理服务器使用
  • 同时存在时,当max-age过期时,则会使用s-maxage

private

res.set("Cache-Control", "max-age=2, s-maxage=20, private");
  • private:只有浏览器才可以缓存

Vary

res.set("Cache-Control", "s-maxage=200");
res.set("Vary", "X-Test-Cache");
  • Vary:发送请求时headers中携带了指定头的值相同才能使用缓存
  • 测试结果是不设置也会命中代理缓存
  • 使用场景:根据User-Agent区分pc,移动端设置不同缓存

HTTPS配置

  • http 转 https
server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name tzhen.vip;
  return 302 https://$server_name$request_uri;
}
  • 配置https
server {
  listen: 443;
  ssl on ;
}

server_push

Link </test.jpg>; as=image;rel=preload nginx: http2_push_perload on;