美文网首页
HTTP协议

HTTP协议

作者: hellomyshadow | 来源:发表于2020-08-25 13:24 被阅读0次

Request

请求行

 GET / HTTP/1.1    // Method、URL、HttpVerson

其中,Method 包括 GET POST HEAD PATCH PUT DELETE TRACE CONNECT OPTIONS

  • CONNECT 保留将来使用
  • OPTIONS
    • 请求查询服务器的性能,或者查询与请求资源相关的功能选项
    • 预检请求

消息报头

  • Accept 指定客户端接受哪些类型的信息(MIME),如image/gif(GIF图片)text/html(HTML文本)
  • Accept-Charset 客户端接受的字符集,如gb2312,utf-8
  • Accept-Encoding 客户端接受的内容编码,如gzip,deflate(压缩类型),identity(默认行为)
  • Accept-Language 客户端接受的自然语言,如zh-cn,zh;q=0.5,zh-cn,zh分别表示简体中文和中文,其中优先支持简体中文,q表示权重系数,范围[0,1],默认值为1;值越大,请求越倾向于 ; 前的类型所表示的内容;如果设置为0,则用于提醒服务器哪些是客户端不支持的内容类型。* 是通配符,表示任意语言。
  • Authorization 证明客户端有权查看某个资源;
  • Host 指定被请求资源的主机和端口号;
  • User-Agent 用户代理:操作系统及版本、CPU类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件;
  • Content-Type Body的编码方式。

请求正文

Response

状态行

 HTTP/1.1 200 OK    // 协议及版本、状态码、状态描述

状态码可分为 5 大类:

  • 1XX 指示信息
  • 2XX 成功
  • 3XX 重定向
  • 4XX 客户端错误
  • 5XX 服务端错误

消息报头

  • 响应报头
    • Location 重定向接受者到一个新的位置
    • WWW-Authontication 包含在401(未授权)的响应消息中
    • Server 包含了服务器用来处理请求的软件信息,如Apache-Coyote/1.1
  • 实体报头
    • Content-Encoding 实体正文的编码
    • Content-Language 资源所用的自然语言。如果没有设置该域,则认为实体内容支持所有语言;
    • Content-Length 正文长度,以字节形式存储的十进制数字来表示
    • Content-Type 实体正文的媒体类型
    • Expires 响应过期的日期和时间

响应正文

跨域

同源策略: 协议protocol、主机host、端口号port 一致
跨域 是浏览器的同源策略所致,与后端无关。HTTP请求正常发送了,后端也正常处理了,只是请求结果被浏览器拦截了。
跨域接口的特征:Network -> General

Referrer Policy: no-referrer-when-downgrade

后端允许跨域的响应头:

// 允许 http://localhost:3000 跨域
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')

设置为 * 则表示所有域名都可以跨域访问。

简单请求与复杂请求

查看 Network 可知,有的请求会发送两次,第一次请求的方法是OPTIONS,也就是预检请求。
为什么会发送预检请求?

我们都知道浏览器的同源策略,出于安全考虑,浏览器会限制从脚本发起的跨域HTTP请求,像AJAX、Fetch都遵循同源策略;
浏览器限制跨域请求一般有两种方式:1> 限制发起跨域请求;2> 跨域请求可以正常发起,但浏览器会拦截返回的结果。
一般浏览器都是第二种方式限制跨域请求,也就是说请求已到达服务器,且有可能操作了数据库,但返回的结果被浏览器拦截了,那么我们就获取不到返回结果。虽然这是一次失败的请求,但可能对数据库里的数据产生了影响。
为了防止这种情况的发生,对这种可能对服务器数据产生副作用的HTTP请求方法,浏览器必须先使用OPTIONS方法发起一个预检请求,从而获知服务器是否允许该跨域请求。如果允许,则发送带数据的真实请求;如果不允许,则阻止发送带数据的真实请求。

由此,HTTP请求分为 简单请求预检请求

  • 简单请求不会触发CORS预检请求
    • GET、HEAD、POST
    • 对于POST请求,Content-Type 的值必须符合 application/x-www-form-urlencoded、multipart/form-data、text/plain,否则视为预检请求。
  • 预检请求要求 必须首先使用 OPTIONS 方法发送一个请求到服务器
    • PATCH PUT DELETE TRACE CONNECT OPTIONS 这些请求默认就是预检请求;
    • 请求头中设置了自定义的字段,即使当前请求属于简单请求,也会被视为预检请求;
      axios.get('/api/users', {
         headers: {
            'X-Token': 'xxxxxxxx'
         }
      })
      
    • Content-Type 的值不属于 application/x-www-form-urlencoded、multipart/form-data、text/plain 中的任何一种。

因此,服务器在允许跨域时,还要额外处理预检请求OPTIONS,允许预检请求跨域!

res.writeHead(200, {
    'Access-Control-Allow-Origin': 'http://localhost:3000',
    'Access-Control-Allow-Headers': 'X-Token,Content-Type',
    'Access-Control-Allow-Methods': 'PUT'
})

跨域中的Cookie

通常在跨域的情况下,Cookie 是无效的,这也是 Session 无效的原因。

  • 服务器让客户端设置Cookie的响应头:
     res.setHeader('Set-Cookie', 'cookie1=va3333')
    
  • 服务端获取Cookie:req.headers.cookie
  • axios发请求默认是不带Cookie的,需要设置:
     axios.defaults.withCredentials = true
    
  • 另外,在服务端的请求中设置允许Cookie,预检请求和真实请求都要加
     res.setHeader('Access-Control-Allow-Credentials', 'true')
    

这样在跨域的情况下也能获取到Cookie

express 设置反向代理,可以解决跨域问题

const express = require('express')
const proxy = require('http-proxy-middleware')
const app = express()
app.use('/api', proxy({
    target: 'http://localhost:4000',
    changeOrigin: false
}))

正向代理与反向代理

  • 正向代理 在客户端,客户端配置代理服务器 去请求目标服务器;如Webpack的代理,VPN
  • 反向代理 在服务端,代理服务器就是客户端请求的目标服务器,但在服务端,这个代理服务器会转发请求到其他机器;NginxNode 常被用做代理请求的服务。

监控

埋点 - 上报信息的方式
AXIOS
img.src
const img = new Image()
img.src='/api/report?xxx=yyy'
//....还有很多

相关文章

网友评论

      本文标题:HTTP协议

      本文链接:https://www.haomeiwen.com/subject/vswnjktx.html