HTTP请求/响应

常见的前后端数据交互方式,不同数据的前后端交互处理

Posted by page on January 4, 2021

HTTP

状态码

  • 1xx 信息
  • 2xx 成功
  • 3xx 重定向
    • 301 永久重定向
    • 302 临时重定向
    • 304 缓存中读取
  • 4xx 请求错误
    • 400 参数验证问题
    • 401 HTTP认证信息问题
    • 403 无权限操作
    • 404 请求资源未找到
    • 405 不允许的请求方法
  • 5xx 服务器错误、
    • 500 服务器内部处理错误
    • 502 网关或代理报错,后端服务重启中或关闭
    • 504 服务超时,后端服务面临大量请求或任务占满

请求头

Content-Type

数据格式类型

get请求时不存在,因为get下请求体为空,不需要请求体的数据格式说明

application/x-www-form-urlencoded post默认数据格式,即表单键值对格式,并urlencoded(编码)

application/json json数据格式,其它数据格式的值会被转为字符串,json被解析后依旧能保留值的数据类型

application/form-data 传输表单数据,支持文件上传和非 ASCII 字符编码

application/octet-stream 二进制流

跨域

现代浏览器的安全性要求遵循同源策略,即浏览器发送的异步请求(ajax)与服务端的响应在协议、域名、端口须全部一致。

否则违反该策略的异步请求会被阻止(blocked);

注意: 跨域是浏览器主动限制/屏蔽后端的响应,而非服务端不对请求响应或不返回数据;

解决

服务端

  • 设置响应头允许跨域,如Access-Control-Allow-Origin: *,允许自定义跨域限制条件
  • 服务器反向代理

JSONP

利用script标签支持异步加载js资源的原理,声明一个异步请求的回调函数,创建一个script标签,通过设置src地址使其向后端发送请求,请求类型仅为get,参数即url上查询串,后端返回script标签内容为一行调用前端声明好的回调函数的代码,将数据作为函数参数;浏览器接收到script资源就会执行js调用声明好的回调函数;

XMLHttpRequest

Formdata

支持获取表单字段发送ajax请求,也可以自定义Formdata对象

  • 例子
let formData = new FormData($formDOM);
// 允许添加自定义的请求字段与值
let formData.append("username","page"); 
let xhr = new XMLHttpRequest();
xhr.open(formDom.method,form.action,true);
xhr.send(formData);
...
// jquery
$.ajax({
    url: formDOM.action,
    type: formDOM.method,
    data: fromData,
    contentType: false,
    processData: false
})
// axios
axios({
  url: API_URL,
  method: 'post',
  data: formData,
  headers: {'Content-Type': 'multipart/form-data'}
});

注意: 使用Formdata上传文件,为form标签添加 entype="multipart/form-data" 即可

Fetch

相对XMLHttpRequest对象,Fetch作为API提供了一个更理想的替代方案,以一种简单,合理的方式来跨网络异步获取资源。

还提供了专门的逻辑空间来定义其他与 HTTP 相关的概念,例如 CORS 和 HTTP 的扩展。

使用

  • fetch(url,{ 请求头配置 }).then(res => res.json()).then(data => ...);

  • async/await 可以这样写

    async function request(url, options, success){
        let res = await fetch(url,options); // http请求
        let data = await res.json();    // 解析响应数据
        success(data);
    }
    
  • 请求配置(options)

    body: JSON.stringify(data), // must match 'Content-Type' header
    cache: 'no-cache', // *default, no-cache, reload, force-cache,only-if-cached
    credentials: 'same-origin', // include, same-origin, *omit
    headers: {
      'user-agent': 'Mozilla/4.0 MDN Example',
      'content-type': 'application/json' 
    },
    method: 'POST', // *GET, POST, PUT, DELETE, etc.
    mode: 'cors', // no-cors, cors, *same-origin
    redirect: 'follow', // manual, *follow, error
    referrer: 'no-referrer', // *client, no-referrer
    
  • 注意

    1. 通过设置body为Formdata对象即上传文件
    2. 不同于XMLHttpRequest,fetch不会将错误状态码作为reject处理,而是resolve
    3. 低版本都不兼容fetch,在模块化开发下,你可以使用

SSE

SSE(Server Send Event)服务器发送事件,实现服务器向web页面推送数据和信息;

通过 js 中 EventSource 接口向服务器开启持久链接

构造事件

// 事件源URL字符串,支持get方式参数
const evtSource = new EventSource("/evt/message?chatId=123");
// 将发起一个 "Content-Type: text/event-stream" 的请求

监听事件

evtSource.onopen = () => {
 console.log("链接打开时");
};
evtSource.onmessage = (e) => {
  console.log(e.data);
};
evtSource.onerror = () => {
 console.log("链接未能打开/错误中断时");
};

关闭链接

evtSource.close();
// EventSource.readyState 0 链接中 1 打开的链接 2 已关闭的链接