前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • HTTP

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
      • HTTP传输大文件
      • HTTP的连接管理
      • HTTP的重定向
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础

# HTTP的实体数据

30 秒速记

  • 实体数据(现在规范里叫「表示」,representation)就是 body,要让对方处理对,得说清四件事
  • 是什么:MIME 类型,Accept ↔ Content-Type
  • 怎么压缩:Accept-Encoding ↔ Content-Encoding
  • 什么语言:Accept-Language ↔ Content-Language;字符集请求用 Accept-Charset,响应写在 Content-Type 的 charset 里
  • 协商规则:客户端列候选 + q 权重,服务器挑一个并用 Content-* 告诉你挑了啥;结果随请求头变的要加 Vary

实体数据就是报文的 body,光有一串字节没用,还得告诉对方它是什么、压没压缩、什么语言、什么字符集。 HTTP 用两组头来对齐这四件事:客户端用 Accept 开头的请求头说「我能接受什么」,服务器用 Content 开头的响应头说「我实际给了什么」,这个过程叫内容协商。比如浏览器发 Accept-Encoding: gzip, br,服务器选了 br 就回 Content-Encoding: br。字符集是个特例,响应里没有 Content-Charset,而是写成 Content-Type: text/html; charset=utf-8。同一个地址如果会按这些请求头返回不同版本,要加 Vary,不然 CDN 可能把压缩版发给不支持的客户端。

HTTP 报文由起始行、头部和 body 三块组成,body 就是这里说的实体数据。早期规范(RFC 2616)叫它 entity,现在的 RFC 9110 改叫 representation,也就是「资源的某一种表示」:同一篇文章可以有 HTML 版和 JSON 版、中文版和英文版、压缩版和原始版,它们都是同一个资源的不同表示。

服务器要挑出最合适的那一个表示,就靠内容协商。四个维度一一对应:

维度 请求头(我能接受) 响应头(我实际给的)
数据类型 Accept Content-Type
压缩方式 Accept-Encoding Content-Encoding
自然语言 Accept-Language Content-Language
字符集 Accept-Charset Content-Type 里的 charset

一次典型的交换长这样:

GET /api/article/42 HTTP/1.1
Accept: application/json, text/html;q=0.8
Accept-Encoding: gzip, br
Accept-Language: zh-CN, en;q=0.5

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Encoding: br
Content-Language: zh-CN
Vary: Accept, Accept-Encoding, Accept-Language
@前端进阶之旅: 代码已经复制到剪贴板

浏览器拿到响应后先按 Content-Encoding 用 br 解压,再按 Content-Type 当成 UTF-8 编码的 JSON 解析。Vary 告诉中间的缓存:这三个请求头不同,拿到的可能是不同版本,不能混用。现实中浏览器很少发 Accept-Charset,服务端也常省略 Content-Language,最常见的组合是请求带 Accept、Accept-Encoding、Accept-Language,响应带 Content-Type、Content-Encoding。

面试官追问

追问 1接口返回的 body 前端解析失败,第一步看什么?
参考回答

先看响应头:Content-Type 是不是 application/json,Content-Encoding 有没有、和实际字节对不对得上,charset 是不是 utf-8。浏览器 Network 面板的 Response 和 Headers 对着看,大部分问题在这一步就能定位。

追问 2Content-Type 和 Content-Encoding 都有 Content 前缀,怎么分清?
参考回答

Content-Type 说内容本身是什么,比如 application/json;Content-Encoding 说传输前额外做了什么压缩,比如 gzip。浏览器先按 Encoding 解压,再按 Type 解析,顺序不能反。

追问 3中文乱码,后端说已经加了 Content-Language: zh-CN,还缺什么?
参考回答

缺 charset。Content-Language 只说内容是中文,不管字节怎么解码。要写 Content-Type: text/html; charset=utf-8,并且实际字节真的是 UTF-8。

追问 4前端能不能自己在 fetch 里设 Accept-Encoding?
参考回答

不能,它是浏览器的禁止修改头,设了也会被忽略,浏览器会按自己的能力填。前端能控制的是 Accept、Accept-Language 这类,比如 fetch(url, { headers: { Accept: 'application/json' } })。

追问 5同一个 URL 按语言返回中英文两个版本,CDN 偶尔给中文用户返回英文,为什么?
参考回答

响应没带 Vary: Accept-Language,CDN 只按 URL 当缓存键,谁先访问就缓存谁的版本。补上 Vary,同时确认 CDN 真的按这个头区分缓存;更稳的做法是把语言放进 URL,比如 /en/ 和 /zh/,对 SEO 也更友好。

# 数据类型与编b码

30 秒速记

  • MIME type = 「大类/小类」,告诉接收方按什么解析:text/html、image/png、application/json
  • 五大类:text、image、audio、video、application(要靠应用解释,JSON、PDF、JS 都在这)
  • application/octet-stream = 「不知道是啥的二进制」,浏览器通常直接当下载处理
  • Encoding type 只管压缩:gzip 最通用,deflate 用得少,br(Brotli)压得更小,浏览器只在 HTTPS 下声明支持
  • 压缩不改变内容类型:压缩过的 PDF 还是 Content-Type: application/pdf + Content-Encoding: gzip

MIME type 说「这是什么」,Encoding type 说「它被怎么压缩过」,两个信息缺一不可。 浏览器看到 text/html 就交给渲染引擎,看到 image/png 就当图片显示,看到 application/octet-stream 就不知道是啥了,一般直接弹下载。压缩是另一层:为了省带宽,服务器可能把内容用 gzip 或 br 压一下,这时候要额外告诉对方用的哪种算法,不然浏览器拿到的是一堆解不开的字节。我常提醒的一点是,压缩不改变内容的本质,HTML 压完还是 text/html,只是多一个 Content-Encoding: gzip。

- text:即文本格式的可读数据,我们最熟悉的应该就是 `text/html` 了,表示超文本文档,此外还有纯文本 `text/plain`、样式表 `text/css` 等。 - `image`:即图像文件,有 `image/gif`、`image/jpeg`、`image/png` 等。 - `audio/video`:音频和视频数据,例如 `audio/mpeg`、`video/mp4` 等。 - `application`:数据格式不固定,可能是文本也可能是二进制,必须由上层应用程序来解释。常见的有 `application/json`,`application/javascript`、`application/pdf` 等,另外,如果实在是不知道数据是什么类型,像刚才说的“黑盒”,就会是 `application/octet-stream`,即不透明的二进制数据

但仅有 MIME type 还不够,因为 HTTP 在传输时为了节约带宽,有时候还会压缩数据,为了不要让浏览器继续“猜”,还需要有一个“Encoding type”,告诉数据是用的什么编码格式,这样对方才能正确解压缩,还原出原始的数据。

比起 MIME type 来说,Encoding type 就少了很多,常用的只有下面三种

  • gzip:GNU zip 压缩格式,也是互联网上最流行的压缩格式;
  • deflate:zlib(deflate)压缩格式,流行程度仅次于 gzip;
  • br:一种专门为 HTTP 优化的新压缩算法(Brotli)

面试官追问

追问 1预览接口返回 application/octet-stream,能不能直接塞给 <img> 显示?
参考回答

有时候能显示,因为浏览器对图片会嗅探字节头,但这是碰运气。正确做法是后端按实际格式返回 image/png、image/jpeg,要下载再配 Content-Disposition: attachment。

追问 2PDF 下载加了 gzip 压缩,后端想把类型改成 application/gzip,对吗?
参考回答

不对,那样客户端解压后不知道该当 PDF 处理。传输压缩用 Content-Encoding: gzip,类型保持 application/pdf

基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • HTTP

    • 基础篇

      • HTTP的前世今生
      • HTTP是什么
      • HTTP世界全览
      • HTTP分层
      • 键入网址到回车发生什么
      • HTTP报文是什么样子的
      • 理解请求方法
      • URI
      • 响应状态码
      • HTTP有哪些特点
      • HTTP优缺点
      • HTTP的实体数据
        • 数据类型与编b码
        • 数据类型使用的头字段
        • 语言类型使用的头字段
        • 内容协商的质量值
        • 内容协商的结果
        • 小结
      • HTTP传输大文件
      • HTTP的连接管理
      • HTTP的重定向
      • HTTP的Cookie机制
      • HTTP的缓存控制
      • HTTP的代理服务
      • HTTP的缓存代理
    • 高级篇

    • 扩展篇

  • 浏览器相关

  • 计算机基础

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

HTTP的实体数据|HTTP协议篇

# HTTP的实体数据

30 秒速记

  • 实体数据(现在规范里叫「表示」,representation)就是 body,要让对方处理对,得说清四件事
  • 是什么:MIME 类型,Accept ↔ Content-Type
  • 怎么压缩:Accept-Encoding ↔ Content-Encoding
  • 什么语言:Accept-Language ↔ Content-Language;字符集请求用 Accept-Charset,响应写在 Content-Type 的 charset 里
  • 协商规则:客户端列候选 + q 权重,服务器挑一个并用 Content-* 告诉你挑了啥;结果随请求头变的要加 Vary

实体数据就是报文的 body,光有一串字节没用,还得告诉对方它是什么、压没压缩、什么语言、什么字符集。 HTTP 用两组头来对齐这四件事:客户端用 Accept 开头的请求头说「我能接受什么」,服务器用 Content 开头的响应头说「我实际给了什么」,这个过程叫内容协商。比如浏览器发 Accept-Encoding: gzip, br,服务器选了 br 就回 Content-Encoding: br。字符集是个特例,响应里没有 Content-Charset,而是写成 Content-Type: text/html; charset=utf-8。同一个地址如果会按这些请求头返回不同版本,要加 Vary,不然 CDN 可能把压缩版发给不支持的客户端。

HTTP 报文由起始行、头部和 body 三块组成,body 就是这里说的实体数据。早期规范(RFC 2616)叫它 entity,现在的 RFC 9110 改叫 representation,也就是「资源的某一种表示」:同一篇文章可以有 HTML 版和 JSON 版、中文版和英文版、压缩版和原始版,它们都是同一个资源的不同表示。

服务器要挑出最合适的那一个表示,就靠内容协商。四个维度一一对应:

维度 请求头(我能接受) 响应头(我实际给的)
数据类型 Accept Content-Type
压缩方式 Accept-Encoding Content-Encoding
自然语言 Accept-Language Content-Language
字符集 Accept-Charset Content-Type 里的 charset

一次典型的交换长这样:

GET /api/article/42 HTTP/1.1
Accept: application/json, text/html;q=0.8
Accept-Encoding: gzip, br
Accept-Language: zh-CN, en;q=0.5

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Encoding: br
Content-Language: zh-CN
Vary: Accept, Accept-Encoding, Accept-Language
@前端进阶之旅: 代码已经复制到剪贴板

浏览器拿到响应后先按 Content-Encoding 用 br 解压,再按 Content-Type 当成 UTF-8 编码的 JSON 解析。Vary 告诉中间的缓存:这三个请求头不同,拿到的可能是不同版本,不能混用。现实中浏览器很少发 Accept-Charset,服务端也常省略 Content-Language,最常见的组合是请求带 Accept、Accept-Encoding、Accept-Language,响应带 Content-Type、Content-Encoding。

面试官追问

追问 1接口返回的 body 前端解析失败,第一步看什么?
参考回答

先看响应头:Content-Type 是不是 application/json,Content-Encoding 有没有、和实际字节对不对得上,charset 是不是 utf-8。浏览器 Network 面板的 Response 和 Headers 对着看,大部分问题在这一步就能定位。

追问 2Content-Type 和 Content-Encoding 都有 Content 前缀,怎么分清?
参考回答

Content-Type 说内容本身是什么,比如 application/json;Content-Encoding 说传输前额外做了什么压缩,比如 gzip。浏览器先按 Encoding 解压,再按 Type 解析,顺序不能反。

追问 3中文乱码,后端说已经加了 Content-Language: zh-CN,还缺什么?
参考回答

缺 charset。Content-Language 只说内容是中文,不管字节怎么解码。要写 Content-Type: text/html; charset=utf-8,并且实际字节真的是 UTF-8。

追问 4前端能不能自己在 fetch 里设 Accept-Encoding?
参考回答

不能,它是浏览器的禁止修改头,设了也会被忽略,浏览器会按自己的能力填。前端能控制的是 Accept、Accept-Language 这类,比如 fetch(url, { headers: { Accept: 'application/json' } })。

追问 5同一个 URL 按语言返回中英文两个版本,CDN 偶尔给中文用户返回英文,为什么?
参考回答

响应没带 Vary: Accept-Language,CDN 只按 URL 当缓存键,谁先访问就缓存谁的版本。补上 Vary,同时确认 CDN 真的按这个头区分缓存;更稳的做法是把语言放进 URL,比如 /en/ 和 /zh/,对 SEO 也更友好。

# 数据类型与编b码

30 秒速记

  • MIME type = 「大类/小类」,告诉接收方按什么解析:text/html、image/png、application/json
  • 五大类:text、image、audio、video、application(要靠应用解释,JSON、PDF、JS 都在这)
  • application/octet-stream = 「不知道是啥的二进制」,浏览器通常直接当下载处理
  • Encoding type 只管压缩:gzip 最通用,deflate 用得少,br(Brotli)压得更小,浏览器只在 HTTPS 下声明支持
  • 压缩不改变内容类型:压缩过的 PDF 还是 Content-Type: application/pdf + Content-Encoding: gzip

MIME type 说「这是什么」,Encoding type 说「它被怎么压缩过」,两个信息缺一不可。 浏览器看到 text/html 就交给渲染引擎,看到 image/png 就当图片显示,看到 application/octet-stream 就不知道是啥了,一般直接弹下载。压缩是另一层:为了省带宽,服务器可能把内容用 gzip 或 br 压一下,这时候要额外告诉对方用的哪种算法,不然浏览器拿到的是一堆解不开的字节。我常提醒的一点是,压缩不改变内容的本质,HTML 压完还是 text/html,只是多一个 Content-Encoding: gzip。

- text:即文本格式的可读数据,我们最熟悉的应该就是 `text/html` 了,表示超文本文档,此外还有纯文本 `text/plain`、样式表 `text/css` 等。 - `image`:即图像文件,有 `image/gif`、`image/jpeg`、`image/png` 等。 - `audio/video`:音频和视频数据,例如 `audio/mpeg`、`video/mp4` 等。 - `application`:数据格式不固定,可能是文本也可能是二进制,必须由上层应用程序来解释。常见的有 `application/json`,`application/javascript`、`application/pdf` 等,另外,如果实在是不知道数据是什么类型,像刚才说的“黑盒”,就会是 `application/octet-stream`,即不透明的二进制数据

但仅有 MIME type 还不够,因为 HTTP 在传输时为了节约带宽,有时候还会压缩数据,为了不要让浏览器继续“猜”,还需要有一个“Encoding type”,告诉数据是用的什么编码格式,这样对方才能正确解压缩,还原出原始的数据。

比起 MIME type 来说,Encoding type 就少了很多,常用的只有下面三种

  • gzip:GNU zip 压缩格式,也是互联网上最流行的压缩格式;
  • deflate:zlib(deflate)压缩格式,流行程度仅次于 gzip;
  • br:一种专门为 HTTP 优化的新压缩算法(Brotli)

面试官追问

追问 1预览接口返回 application/octet-stream,能不能直接塞给 <img> 显示?
参考回答

有时候能显示,因为浏览器对图片会嗅探字节头,但这是碰运气。正确做法是后端按实际格式返回 image/png、image/jpeg,要下载再配 Content-Disposition: attachment。

追问 2PDF 下载加了 gzip 压缩,后端想把类型改成 application/gzip,对吗?
参考回答

不对,那样客户端解压后不知道该当 PDF 处理。传输压缩用 Content-Encoding: gzip,类型保持 application/pdf。只有用户真的要下载一个 .gz 文件时,才用 application/gzip。

追问 3gzip 和 br 怎么选?
参考回答

文本类静态资源优先 br,同等条件下通常比 gzip 小一截,适合构建时预压缩;动态内容实时压缩时 br 高压缩级别很吃 CPU,常用中低级别或者继续用 gzip。两种都备着,按 Accept-Encoding 挑,HTTP 页面上浏览器一般不会声明 br。

追问 4服务端把 JS 文件返回成 text/plain,页面脚本突然不执行了,为什么?
参考回答

如果响应带了 X-Content-Type-Options: nosniff,浏览器会严格按 MIME 判断,text/plain 的脚本直接拒绝执行。把类型改成 text/javascript(或 application/javascript)就行,这个头本身是安全加固,别为了省事删掉。

追问 5为什么图片、视频一般不再压缩?
参考回答

JPEG、PNG、MP4 这些格式本身就是压缩过的,再套一层 gzip 基本压不动,有时还会大一点,白白浪费 CPU。真要变小得从格式下手,比如换 WebP、AVIF。

# 数据类型使用的头字段

30 秒速记

  • 两组成对的头:Accept ↔ Content-Type 管类型,Accept-Encoding ↔ Content-Encoding 管压缩
  • 请求侧列候选,逗号分隔:Accept: text/html,application/xml,image/webp
  • 响应侧写实际结果:Content-Type: image/png、Content-Encoding: gzip
  • 响应没有 Content-Encoding = 没压缩;请求没带 Accept-Encoding 时,稳妥做法是别压缩(Nginx 就是这么处理的)
  • Accept-Encoding 由浏览器自动填,前端 JS 改不了

内容协商就是客户端先报「我能接受什么」,服务器再回「我实际给了什么」,类型和压缩各有一对头。 请求里 Accept 列出能处理的类型,Accept-Encoding 列出能解的压缩格式,都可以用逗号写多个,给服务器留选择余地;响应里 Content-Type 写实际类型,Content-Encoding 写实际用的压缩算法。浏览器完全靠响应头决定怎么处理 body,所以响应头要和真实内容一致。至于请求没带 Accept-Encoding,规范上其实说任何编码都算可接受,但实际服务器都会保守处理,直接返回不压缩的原始数据,避免老客户端解不开。

← HTTP优缺点HTTP传输大文件 →

fe