http请求之简单请求与非简单请求

245 阅读2分钟

简单概念

  • 简单请求满足以下条件
    • 请求方式为以下之一:HEAD、GET、POST
    • 除了被用户代理自动设置的首部字段(例如 ConnectionUser-Agent)和在 Fetch 规范中定义为 禁用首部名称 的其他首部,允许人为设置的字段为 Fetch 规范定义的 对 CORS 安全的首部字段集合。该集合为::Accept、Accept-Language、Content-Language、Content-Type
    • Content-Type(仅限于text/plain、multipart/form-data、application/x-www-form-urlencoded)
    • 请求中的任意 XMLHttpRequest 对象均没有注册任何事件监听器;XMLHttpRequest 对象可以使用 XMLHttpRequest.upload 属性访问。
    • 请求中没有使用 ReadableStream 对象。
  • 非简单请求
    • 使用了下面任一 HTTP 方法,PUT/DELETE/CONNECT/OPTIONS/TRACE/PATCH
    • 人为设置了以下集合之外首部字段,即简单请求外的字段 - Content-Type 的值不属于下列之一,即application/x-www-form-urlencoded、multipart/form-data、text/plain

非简单请求在真正的请求之前,浏览器会发送一个预检请求OPTIONS,该请求用来确认目标请求是否支持跨域,如果不允许则控制台报错;如果允许则发送后续请求。 发送OPTIONS请求返回响应头中会包含Access-Control-Allow-Methods表明服务器允许客户端使用什么方法发起请求,Access-Control-Allow-Origin允许跨域请求的域名,如果要允许所有域名则设置为,Access-Control-Max-Age指定了预检请求的结果能够被缓存多久。浏览器根据返回的内容进行判断

优化OPTIONS请求方式:

  • 对 options 请求进行缓存,浏览器会根据返回的 Access-Control-Max-Age 字段缓存该请求的 OPTIONS 预检请求的响应结果(具体缓存时间还取决于浏览器的支持的默认最大值,取两者最小值,一般为 10 分钟)。在缓存有效期内,该资源的请求(URL 和 header 字段都相同的情况下)不会再触发预检。(chrome 打开控制台可以看到,当服务器响应 Access-Control-Max-Age 时只有第一次请求会有预检,后面不会了。注意要开启缓存,去掉 disable cache 勾选
  • 转为简单请求,如用 JSONP 做跨域请求