我不想做一只菜🐦--记一次对http的学习

573 阅读7分钟

HTTP原理

常见的http场景

  • url到网页展示
  • ajax获取数据
  • img标签加载图片

五层网络模型

  • 应用层:
    • 作用:为应用软件提供了更多的服务(http服务),构建于tcp协议之上(网络传输优化),屏蔽了网络传输相关细节。
  • 传输层:
    • 分类:TCP|UDP
    • 作用:向用户提供了可靠的端到端的服务,向高层屏蔽了下层数据通信的细节。
  • 网络层:
    • 作用:在节点之间传输创建逻辑链路。
  • 数据链路层:
    • 作用:在通信的实体间建立数据链路链接。
  • 物理层:
    • 作用:定义物理设备如何传输数据

5层网络模型.png

http协议发展史

tcp的三次握手

  • 本质:http request 是建立在 TCP connection 之上的,建立 TCP connection 需要进行三次🤝
  • 三次🤝的意义:当服务器端向客户端传输数据包出现丢失的使用,确保客户端正常收到了数据,避免服务器端开启无用的服务

URI URL URN

  • URI:统一资源标志符,用来唯一标识互联网上的信息资源,它包括了URL和URN。
  • URN:永久统一资源定位符。
  • URL:统一资源定位器[schema+host+port+path+serach]
  • schema:定义请求的发送方如何发送数据,和请求的接收方如何解析数据;约束传输数据的格式
  • host:物理服务器主机的地址。
  • port:定位物理服务器上运行的web服务器。
  • path:路由对应到web服务结构下到路径。
  • serach:通过url传递给服务器到参数

http报文格式

  • 请求报文格式
格式 内容
首行 请求方法 路由 http协议版本
首部 Accept:text/*
  • 响应报文格式
格式 内容
首行 http协议版本 状态码 状态信息
首部 Content-type:text/plain Cache-control:max-age=2000
主体 i'm a message

跨域资源共享(cors)

  • 定义:CORS (Cross-Origin Resource Sharing,跨域资源共享)是一个系统,它由一系列传输的HTTP头组成,这些HTTP头决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应.

  • 跨域是发生在浏览器端[请求已经发送到了服务器,服务器也做出了响应]

sequenceDiagram
浏览器端-->>服务器端: 发送一个跨域的请求
服务器端-->>浏览器端: 服务器收到请求,并返回响应的结果

  // 设置允许跨域
  reponse.writeHead(200, {
      // script img link 标签是允许跨域的
      // * 表示所有的域名都可以访问到指定的域名
      "access-control-allow-origin": *
      "access-control-allow-header": "设置允许的请求头"
      "access-control-allow-methods": "设置允许的请求方法"
      "access-control-max-age":"设置在指定时间里,浏览器不需要发送预请求进行验证"
  })
  • cors的预请求:浏览器得到服务器允许访问请求资源的一种方式。
   // 当发生跨域的时候,浏览器默认只允许GET|HEAD|POST请求,其他方法浏览器都会有预请求验证的
   // 允许的content-type, text/plain | multipart/form-data|application/x-www-form-urlencoded
   // 请求头限制:Accept|Accept-Language|Content-Language|Content-Type|DPR|Downlink|Save-Data|Viewport-Width|Width

缓存 Cache-Control(客户端缓存)

强缓存

  • 问题:当静态资源发送变化的时候,客户端无法感知到服务器端的静态资源发生了变化,浏览器端还是会使用缓存。导致请求之前的资源。[前端使用hash进行刷新缓存]

协商缓存

chrome中的 disable-cache

服务器端如何做etag

缓存

  • 可缓存性:
  • public:资源可以被浏览器缓存,也可以被代理服务器缓存
  • private:资源只能被浏览器缓存
  • no-cache(协商缓存):本地可以有缓存,但是每次请求都必须向服务器请求认证缓存的可用性, 确定是否使用浏览器缓存。
  • 缓存时间设置:
  • max-age: Cache-Control: max-age=
  • s-maxage: 在代理服务器端,优先级大于max-age
  • max-stale:
  • 重新验证:
  • must-revalidate
  • proxy-revalidate
  • 限制缓存
  • no-cache:本地可以有缓存,但是每次请求都必须向服务器请求认证缓存的可用性, 确定是否使用浏览器缓存。
  • no-store:不使用缓存
  • no-transform:约束代理服务器端,不能更改资源.
  • 缓存验证:
  • Last-Modified(if-Modified-Since):记录上次资源修改的时间
  • ETag(if-Non-Match):一个资源对应一个唯一的签名
   // 设置max-age
   reponse.writeHead(200, {

       "Cache-Control": 'max-age = 2000,public',
       "Content-Type": "text/javascript""Last-Modified": "123",
       "Etag": "777"

   })
   const eTag = request.header['if-none-match'];
   if (eTag === '777') {
       // 304 重定向
       reponse.writeHead(304, {

           "Cache-Control": 'max-age = 2000,public',
           "Content-Type": "text/javascript""Last-Modified": "123",
           "Etag": "777"

       })
       response.end('')
   } else {
       reponse.writeHead(200, {

           "Cache-Control": 'max-age = 2000,public',
           "Content-Type": "text/javascript""Last-Modified": "123",
           "Etag": "777"

       })
       response.end('asd')
   }

cookie[Set-Cookie]和session

  • 作用:在同域名下进行资源访问,浏览器 所有请求会自动带上cookie[可能存在多余性能问题:通常通过将不需要cookie认证的静态资源和需要认证的接口放在不同的域名下面],request头中的Cookie字段。
  • 设置cookie
  // 服务器端通过设置 Set-Cookie,设置给浏览的值。
  // 时期:max-age和expires设置过期时间,或者关闭浏览器
  // Secure只在https的时候发送
  // 设置HttpOnly 无法通过document.cookie访问
  // 同一个主域名下的所有二级域名都可以访问到cookie
  res.writeHead(200, {
      // 数组设置多个cookie:响应头中将出现两个Set-Cookie字段
      // 单个键值对:设置单个cookie
      // max-age:设置cookie的过期时间
      // HttpOnly:被设置的cookie无法通过document.cookie访问。
      // domain:cookie不能进行跨域设置
      "Set-Cookie": ["key=value;max-age=2", "key1=value1;HttpOnly", "key2=value2;domain=test.com"]
  })

http长连接[Connection]

  • 定义:http的请求是基于tcp发送的,tcp的连接分为长连接和短连接
  // Response Header
  // Chrome最多允许6个并发的tcp连接。
  // Connection
  res.writeHead(200, {
      "Connection": "close",//关闭调长链接,每次请求都会走三次握手重新建立tcp连接
      "Connection": "keep-alive"(默认值)
  })
  // http2中 允许一个tcp连接并发多个http请求(信导复用)

数据协商[Accept]

  • 定义:请求端通过发送不同的头信息,来约束服务端返回数据的格式
  • 请求头:
   Accept: 申明想要请求数据的类型
   Accept-Encoding: 请求的编码格式, 通常用来约束服务端使用什么压缩算法
   Accept-Language: zh-CN, zh;q = 0.9(q表示权重)
   User-agent: 浏览器的相关信息
   Content-Type: 客户端会根据Content-Type, 输出不同的payload格式
  • 响应头:
   Content-Type: 服务端返回的数据格式
   X-Content-Type-Options: "nosniff"
   Content-Encoding: 告诉客户端服务端使用的是什么压缩算法
   Content-Language:
  • node中开启gzip
    const zlib = require('zlib');

重定向[redirect]

  • 状态码:3xx,浏览器端根据状态码,来决定自身的行为
  • 302 临时重定向:需要服务器端的一次location,重新定向到新的地址
  • 301 永久重定向:浏览器直接使用缓存
 if (request.url === '/') {
    response.writeHead(302, {
        'Location': '/new' // 同域的情况下 可以不写协议和域名
    })
}

if (request.url === '/new') {
    response.writeHead(200, {
        'Content-Type': 'text/html'
    })
    response.end('<div>this is content</div>')
}

CSP(content-security-policy)

  • mdn

  • 作用:限制资源获取,报告资源获取越权.

  • 主要目标:CSP 的主要目标是减少和报告 XSS 攻击 ,XSS 攻击利用了浏览器对于从服务器所获取的内容的信任。恶意脚本在受害者的浏览器中得以运行,因为浏览器信任其内容来源,即使有的时候这些脚本并非来自于它本该来的地方。

  • 限制方式:例如 default-src限制全局

      response.writeHead(200, {
          'Content-Security-Policy': 'default-src http: https:'
      })

      //只能加载同域下的外链js脚本
      response.writeHead(200, {
          'Content-Security-Policy': 'default-src \'self'\
          '
      })

      //向服务器报告
      response.writeHead(200, {
              'Content-Security-Policy': 'default-src \'self'\;report / server 'address '
      })

      // meta标签实现
      <meta http-equiv = 'Content-Security-Policy'
      content = 'default-src http: https' >