HTTP报头Accept与Content-Type的区别

联调时出现mediatype的报错,属于Content-Type配错了,回来补充下这方面的知识点

对比 请求报文、响应报文

请求报文响应报文对比图示+实体首部字段

Accept属于请求头, Content-Type属于实体头

  • Accept属于 请求首部字段,只有HTTP请求有。
  • Content-Type属于 实体首部字段HTTP请求和响应 都拥有该字段。
    • 注意:get请求和post请求默认 Content-Type 是 application/json,但是 GET 请求不会带有请求体(request body),它是字符串拼接的?id=123这种,因此 Content-Type 的设置对 GET 请求并不产生影响。

Accept代表发送端(客户端)希望接受的数据类型

比如:

1
2
// 代表客户端希望接受的数据类型是json类型
Accept:"application/json";

Content-Type代表发送端(客户端/服务器)发送的实体数据的数据类型

比如:

1
2
// 代表发送端发送的数据格式是json
Content-Type:"application/json";

二者结合在请求头中

二者合起来在请求头中,代表希望接受的数据类型是json格式,本次请求发送的数据的数据格式是json:

1
2
Accept:"application/json"
Content-Type:"application/json"

常见的媒体类型(MediaType)

  • AcceptContent-Type的常见值(即 的媒体类型(MediaType)):
    • text/html:HTML格式
    • text/plain:纯文本格式
    • text/xml: XML格式
    • image/gif:gif图片格式
    • image/jpeg:jpg图片格式
    • image/png:png图片格式
    • application/xhtml+xml:XHTML格式
    • application/xml: XML数据格式
    • application/atom+xml:Atom XML聚合格式
    • application/json:JSON数据格式
    • application/pdf:pdf格式
    • application/msword: Word文档格式
    • application/octet-stream: 二进制流数据(如常见的文件下载)
    • application/x-www-form-urlencoded:<form encType="">中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格- 式)
    • multipart/form-data: 需要在表单中进行文件上传时,就需要使用该格式
  • "Accept: */*":表示客户端(通常是浏览器)能够接受所有类型的响应。这通常是用在浏览器向服务器请求页面时使用的,告诉服务器客户端能够处理任何返回的内容类型。
    • 例如,在请求中包含 "Accept: */*" 头字段,表示客户端能够处理的响应类型可以是 HTML、XML、JSON 等。

使用场景

处理调用接口时的报错

  • 报mediatype错时,一般是前端调用接口时发出的请求头Content-Type与后端写接口时规定的希望接收到的数据格式不符,更改请求头中Content-Type即可
    • 比如:前端发出的Content-Typeapplication/jsonJSON数据格式,但是后端要application/x-www-form-urlencoded,自然就报错了
    • h12-header中可查看前端发出的请求头
    • 注意:后端希望接收到的数据格式 和 响应头的Content-Type没关系,并不是要请求头中Content-Type与响应头的Content-Type一致就不会报错。明确,响应头Content-Type是说明后端会 发送 的数据格式,而这里的问题是前端 发送 的数据格式Content-Type)和后端希望 接收 到的数据格式不符。

axios配置请求头content-type

  • Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。
  • 设置方法、配置的优先级 可参考文档的例子,非常详细
  • axios 发送post请求时默认是直接把 json 放到请求体中提交到后端的,axios默认的请求头content-type类型是application/json;charset=utf-8
    • axios可自动转换 JSON 数据,从后端获取的JSON数据并不需要通过JSON方法去转换为JS对象,直接就可使用JS对象。
  • content-type三种常见数据格式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 1 默认的格式请求体中的数据会以json字符串的形式发送到后端
    'Content-Type: application/json ' // 默认

    // 2 请求体中的数据会以普通表单形式(键值对)发送到后端
    'Content-Type: application/x-www-form-urlencoded'

    // 3 它会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件
    // 常见前端页面上传个人图像,然后点击保存发送后端修改原始数据
    'Content-Type: multipart/form-data'

设置方法

  • 我最常用到的是post请求的’application/x-www-form-urlencoded’和’application/json’,这里用设置为表单类型为例
    • 毕竟json格式是默认的,也不需要另外设置
    • get请求没有请求体,也不需要设置content-type,get的参数会将查询字符串设置为?id=123&type=user这种,请求体是空的
  • 最常用的是调用接口的时候进行设置:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    import Qs from 'qs' // qs库是 axios 里面包含的,不需要再下载

    let params= {"name": "ll","age": "18"} // 传参

    // ...async函数中...
    const res = await axios({
    headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
    },
    method: 'post',
    url: url, // 调用的接口
    data: Qs.stringify(params) // 为啥有的application/x-www-form-urlencoded需要qs转换可看下方解释,注意:如果是Content-Type是json格式,data接收的就是对象而不是这样的字符串
    })
  • 改变全局 axios 默认值:
    1
    2
    3
    axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
    // 或
    axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
  • 给自定义实例设置默认值:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 方法1:创建实例时配置默认值
    const DkAxios = axios.create({
    headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
    },
    });

    // 方法2:创建实例后修改默认值
    DkAxios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';

    // 方法1和2实际使用方法...async函数中...
    const res1 = await DkAxios({
    method: 'post',
    url: url, // 调用的接口
    data: Qs.stringify(params)
    })

    // 方法3:调用实例时设置
    const res2 = await DkAxios({
    method: 'post',
    url: url, // 调用的接口
    headers: { 'content-type': 'application/x-www-form-urlencoded' },
    data: Qs.stringify(params)
    })

使用qs.stringify(data)的场景和原因

  • 当使用 Axios 发送 POST 请求时,默认使用 Content-Type: application/json 头部,并将请求数据转换为 JSON 字符串
    • Axios 使用了默认的请求拦截器(request interceptor),在发送请求之前会自动对请求数据进行转换
    • 这适用于大多数情况,特别是当使用 JSON 作为数据格式进行数据交换时
  • headers中的Content-Type被设置为application/x-www-form-urlencoded时,需要将data(请求数据)转换成URLSearchParams对象(即表单数据格式),也就是key1=value1&key2=value2这样的形式,然后再发送HTTP请求。这就需要使用qs.stringify(data)方法进行手动序列化,然后再将序列化后的数据作为请求体data发送
    • 注意:手动序列化后的数据应该是一个字符串,而不是对象。因此在请求时,需要将序列化后的数据直接作为请求体传递给Axios,而不是将其包装在一个对象中。(上面例子中可看到)

参考

, ,