body-parser:unsupported content encoding 错误

简介: 最近遇到了一个奇怪的问题,关于body-parser报错,我本地调用没问题,使用测试工具没问题,这种方案都没问题,就和我对接的程序调用有问题,于是开始了面向百度编程,查到了两种解决方案:

最近遇到了一个奇怪的问题,关于body-parser报错:

UnsupportedMediaTypeError: unsupported content encoding "utf-8"
    at contentstream (C:\workspace\xxx\node_modules\body-parser\lib\read.js:181:13)
    at read (C:\workspace\xxx\xxx\body-parser\lib\read.js:56:14)
    at urlencodedParser (C:\workspace\xxx\node_modules\body-parser\lib\types\urlencoded.js:116:5)
    at Layer.handle [as handle_request] (C:\workspace\xxx\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (C:\workspace\xxx\node_modules\express\lib\router\index.js:328:13)
    at C:\workspace\xxx\node_modules\express\lib\router\index.js:286:9
    at Function.process_params (C:\workspace\xxx\node_modules\express\lib\router\index.js:346:12)
    at next (C:\workspace\xxx\node_modules\express\lib\router\index.js:280:10)
    at jsonParser (C:\workspace\xxxt\node_modules\body-parser\lib\types\json.js:119:7)
    at Layer.handle [as handle_request] (C:\workspace\xxx\node_modules\express\lib\router\layer.js:95:5)

于是开始了面向百度编程,查到了两种解决方案:

解决方案1:

const app = express();
// 加上下面的代码,一定要放在 `express()`下面第一句
app.use((req, res, next) => {
   
   
    if (req.headers['content-encoding'] === 'utf-8') {
   
   
        delete req.headers['content-encoding'];
    }
    next();
});

这种方式我不能说推荐,也不能说不推荐,因为这里只是过滤utf-8,如果还有其他的怎么办?再写?至于为什么会有其他的等会再讨论,至于上面的代码什么意思等会在解读。

解决方案2:

修改node_modules/body-parser/lib/read.js中的代码,在第181-184行:

switch (encoding) {
   
   
  case 'deflate':
    stream = zlib.createInflate()
    debug('inflate body')
    req.pipe(stream)
    break
  case 'gzip':
    stream = zlib.createGunzip()
    debug('gunzip body')
    req.pipe(stream)
    break
  case 'identity':
    stream = req
    stream.length = length
    break
  default:
    // throw createError(415, 'unsupported content encoding "' + encoding + '"', {
   
   
    //   encoding: encoding,
    //   type: 'encoding.unsupported'
    // })
    // 注释上面的,修改成下面的
    stream = req
    stream.length = length
}

image.png

上面这种方式是能彻底根治这个问题的,比上面的方式要好,但是还是有多人协同的问题,版本升级的问题。

问题是解决了,但是看到这个文件也就208行代码,我就读一下,为什么会出现这个问题,也顺便了解了第一种方式工作方式。

read.js代码解读

其实这个代码很简单,至于这个问题的原因,主要是在下面的这个方法上面,也就是我们修改的代码:

/**
 * Get the content stream of the request.
 *
 * @param {object} req
 * @param {function} debug
 * @param {boolean} [inflate=true]
 * @return {object}
 * @api private
 */

function contentstream (req, debug, inflate) {
   
   
  // 获取请求头 content-encoding 的值,如果没有 encoding 的值就为 identity
  var encoding = (req.headers['content-encoding'] || 'identity').toLowerCase()

  // 获取请求头 content-length 的值
  var length = req.headers['content-length']
  var stream

  // 判断 encoding 的值是什么,也就是 content-encoding 的值是什么,其实这下面的都是内容压缩的方式
  switch (encoding) {
   
   
    // deflate 压缩
    case 'deflate':
      stream = zlib.createInflate()
      debug('inflate body')
      req.pipe(stream)
      break

    // gzip 压缩
    case 'gzip':
      stream = zlib.createGunzip()
      debug('gunzip body')
      req.pipe(stream)
      break

    // 不做压缩
    case 'identity':
      stream = req
      stream.length = length
      break

    // 其他的就报错了
    default:
      throw createError(415, 'unsupported content encoding "' + encoding + '"', {
   
   
        encoding: encoding,
        type: 'encoding.unsupported'
      })
  }

  return stream
}

可以看到这里的重点就在于content-encoding上面,content-encoding = 'utf-8'utf-8不是编码格式的?怎么会有问题呢?百度都是修改这个工具包的源码,这工具有问题?那为啥这么多人在用,作者也不修改呢?一定有猫腻!!!

content-encoding 属性的含义

经过大量查询资料之后,发现content-encoding的作用是标记消息体应该使用什么编码类型进行编码,以及编码的顺序,主要用于在不丢失原媒体类型内容的情况下压缩消息数据。

它还有一个配套属性accept-encoding,它的作用是用来标识客户端能够理解的内容编码方式。

accept-encoding的意思是:我只认识gzip或者deflate,表达为accept-encoding='gzip,deflate',你不要给我其他的;

content-encoding的意思是:我现在给你数据是经过gzip处理过的,你需要对数据进行处理一下才能认识,表达为content-encoding='gzip'

那么content-encoding='uft-8'好像也破案了,我的内容是utf-8的,你不用gbk给我处理了,不然你不认识;


????????????????????????????????????????????????????

content-type说你抢我的活?你干嘛呀!哎哟~

006APoFYly8h4la4dyriag30500501as.gif

我也不逗机灵了,下面的是mdn上面的描述

实体消息首部 (en-US) Content-Encoding 列出了对当前实体消息(消息荷载)应用的任何编码类型,以及编码的顺序。它让接收者知道需要以何种顺序解码该实体消息才能获得原始荷载格式。 Content-Encoding 主要用于在不丢失原媒体类型内容的情况下压缩消息数据。

请注意原始媒体/内容的类型通过 Content-Type 首部给出,而 Content-Encoding 应用于数据的表示,或“编码形式”。如果原始媒体以某种方式编码(例如 zip 文件),则该信息不应该被包含在 Content-Encoding 首部内。

第二句就一下描述出问题了,所以是很多库的作者自己弄错了含义,给我们带来一大堆的问题,关键是很多库现在的体量已经很大了,就比如我遇到这个问题的,和我对接的程序是Java写的,具体的我不知道用的什么,然后网上也看到了很多库都无法修改这个属性值。

结束

不知道怎么评价这个bug,你说是bug吧,库的作者确实是按照规范来做的,你说不是bug吧,可以上升到线上重大故障。

上面的方案推荐第一种,因为改源码确实会有很多问题,除非你自己去维护这个代码,不到万不得已不建议修改源码。

参考Content-Encoding

目录
相关文章
|
2月前
|
JSON Java 数据格式
使用postMan调试接口出现 Content type ‘multipart/form-data;charset=UTF-8‘ not supported“
本文介绍了使用Postman调试接口时遇到的“Content type ‘multipart/form-data;charset=UTF-8’ not supported”错误,原因是Spring Boot接口默认只接受通过`@RequestBody`注解的请求体,而不支持`multipart/form-data`格式的表单提交。解决方案是在Postman中将请求体格式改为`raw`并选择`JSON`格式提交数据。
使用postMan调试接口出现 Content type ‘multipart/form-data;charset=UTF-8‘ not supported“
|
XML JSON 人工智能
Error while extracting response for type [class xxx] and content type application/xml;charset=UTF-8
Error while extracting response for type [class xxx] and content type application/xml;charset=UTF-8
1162 0
|
4月前
|
JSON 数据格式
Content type ‘text/plain;charset=UTF-8‘ not supported,这里要把测试文件转为json格式
Content type ‘text/plain;charset=UTF-8‘ not supported,这里要把测试文件转为json格式
|
6月前
|
XML 数据格式
restTemplat发post请求报错Content type ‘application/xml;charset=UTF-8‘ not supported“
restTemplat发post请求报错Content type ‘application/xml;charset=UTF-8‘ not supported“
248 1
|
6月前
|
JSON Java 数据格式
Could not extract response: no suitable HttpMessageConverter found for ..content type [text/html...]
Could not extract response: no suitable HttpMessageConverter found for ..content type [text/html...]
693 0
|
JSON 数据格式
Content type ‘multipart/form-data;boundary=------57031299820747271;charset=UTF-8‘ not supported的解决方案
Content type ‘multipart/form-data;boundary=------57031299820747271;charset=UTF-8‘ not supported的解决方案
303 0
|
JSON Java 数据格式
HttpMediaTypeNotSupportedException: Content type ‘application.yml/json;charset=UTF-8‘ not supported
HttpMediaTypeNotSupportedException: Content type ‘application.yml/json;charset=UTF-8‘ not supported
340 0
|
XML 数据安全/隐私保护 数据格式
Minio出现Non-XML response from server. Response code: 400, Content-Type: text/xml; ch的解决
Minio出现Non-XML response from server. Response code: 400, Content-Type: text/xml; ch的解决
3440 0
|
XML JSON 前端开发
Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
讲述ajax请求后端传参报 Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported问题处理
 Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported
|
JSON PHP 数据格式
php json_encode JSON_ERROR_UTF8 Malformed UTF-8 characters, possibly incorrectly encoded
php json_encode JSON_ERROR_UTF8 Malformed UTF-8 characters, possibly incorrectly encoded
377 0