眼前一亮的HTTP 🌐

🌐 HTTP协议基础

什么是HTTP?

HTTP(HyperText Transfer Protocol)超文本传输协议是互联网上应用最为广泛的一种网络协议。它是一个基于请求-响应模式的、无状态的应用层协议,常基于TCP协议传输。

OSI七层协议模型

 1┌─────────────┐
 2应用层(7)   │ ← HTTP/HTTPS/FTP/SMTP
 3├─────────────┤
 4表示层(6)   │ ← SSL/TLS加密
 5├─────────────┤
 6会话层(5)   │ ← 建立/管理/终止会话
 7├─────────────┤
 8传输层(4)   │ ← TCP/UDP
 9├─────────────┤
10网络层(3)   │ ← IP
11├─────────────┤
12数据链路层(2)│ ← 以太网
13├─────────────┤
14物理层(1)   │ ← 物理传输介质
15└─────────────┘

面试考点:能够清晰说出HTTP位于应用层,基于TCP协议,并理解各层的作用。

🚀 HTTP版本演进史

 

 

 

 

HTTP/0.9 (1991年) - 最简单的版本

特点:

  • 只支持 GET 请求
  • 没有请求头(Header)
  • 只能传输 HTML文本
  • 请求完成后立即关闭连接
 1GET /index.html

面试考点:这是HTTP最初版本,功能极其简单,为后续版本奠定基础。

HTTP/1.0 (1996年) - 多媒体时代

核心改进:

  • ✅ 引入了请求头和响应头
  • ✅ 支持多种数据类型(图片、CSS、JS等)
  • ✅ 引入了状态码概念
  • ✅ 支持Cookie(但仍然是无状态协议)
 1GET /image.jpg HTTP/1.0
 2Host: www.example.com
 3User-Agent: Mozilla/5.0
 4Accept: image/jpeg, image/png
 5
 6HTTP/1.0 200 OK
 7Content-Type: image/jpeg
 8Content-Length: 12345
 9Set-Cookie: session=abc123
10
11[二进制图片数据]

缺点:

  • 每次请求都需要重新建立TCP连接
  • 连接无法复用,性能开销大

HTTP/1.1 (1997年) - 长连接时代

重大改进:

1. 持久连接(Keep-Alive)
  • 推出了长链接 -Connection: keep-alive
    一个TCP可以处理多个请求,浏览器通过一个TCP连接连续请求 页面、图片、脚本等多个资源,服务器处理完不会立刻断开,而是 保持链接。后续请求无需重新建立链接,节省时间和性能开销, 提高加速速度。
 1GET / HTTP/1.1
 2Host: www.example.com
 3Connection: keep-alive
 4
 5HTTP/1.1 200 OK
 6Connection: keep-alive
 7Keep-Alive: timeout=5, max=100
2. 管道化(Pipelining)

管道化 pipelining 允许同时发送多个请求 你用支持管道化的浏览器,依次发送 获取首页、图片1,图片2,无需等待前一个响应。但服务器必须按顺序返回。

  • 允许在同一连接上并发发送多个请求
  • 但响应必须按顺序返回
3. 分块传输编码

TCP 可靠的传输,一个通信的多个数据包,按顺序、全部到达浏览器。 没有能真正并发,TCP 安全 响应时还是顺序的传输 队头阻塞 如果排在前面的资源传输慢,后面的资源没办法传输

 1HTTP/1.1 200 OK
 2Transfer-Encoding: chunked
 3
 45\r\n
 5Hello\r\n
 66\r\n
 7World!\r\n
 80\r\n
 9\r\n

存在问题:

  • 队头阻塞:前面请求慢会阻塞后面请求
  • 同域名并发限制:浏览器通常限制6个并发连接

HTTP/2.0 (2015年) - 多路复用时代

革命性改进:

1. 二进制分帧
  • 二进制分帧 所有请求和响应都被拆成小数据帧,通过一个链接并发传输,每个帧带有编号, 制定是哪个文件,客户端和服务端可以根据编号,组装数据。 无需排队,谁先准备好谁就先发、解决了对头阻塞的问题。
 1文本协议二进制协议
 2┌─────────────┐    ┌─────────────┐
 3Header   │ →  │   Headers
 4Frame    │    │    Frame
 5├─────────────┤    ├─────────────┤
 6Data    │ →  │    Data
 7Frame    │    │    Frame
 8└─────────────┘    └─────────────┘
2. 多路复用(Multiplexing)
  • 并发 多路复用 一个TCP 链接上并发多个请求,不再队头阻塞。 多轮复用把数据拆分成多个帧,通过一个链接并发传输。
 1HTTP/1.1: 一个连接同时只能处理一个请求
 2┌─────┐ ┌─────┐ ┌─────┐
 3请求1 │ │请求2 │ │请求3
 4└──┬──┘ └──┬──┘ └──┬──┘
 5等待等待
 6   ▼       ▼       ▼
 7┌─────────────────────────┐
 8服务器
 9└─────────────────────────┘
10
11HTTP/2.0: 一个连接可以并发处理多个请求
12┌─────┐ ┌─────┐ ┌─────┐
13请求1 │ │请求2 │ │请求3
14└──┬──┘ └──┬──┘ └──┬──┘
15并发并发
16   ▼       ▼       ▼
17┌─────────────────────────┐
18服务器
19└─────────────────────────┘
3. 头部压缩(HPACK)
  • 头部压缩 减少重复header 传输。
  • 使用HPACK算法压缩请求头
  • 维护头部字段表,避免重复传输
4. 服务器推送(Server Push)
  • 服务器端推送 server push 服务器端可主动推送资源。首页GET/返回很快,但首屏还依赖app.css app.js 等,为了减少首轮返回的时间,服务器端可以主动推送。

HTTP/3.0 (2020年) - QUIC时代

基于QUIC协议(UDP):

  • 解决了TCP的队头阻塞问题
  • 更快的连接建立
  • 更好的移动网络支持

⚡怎么优化网页加载速度,在通信这块?

通信层面的网页加载优化策略

 

 

 

 

  1. 路由懒加载与分包
    将应用按路由拆分为独立的模块(如 Login.jsxApp.jsx),在用户访问对应页面时才按需加载,减少首屏体积,加快初始加载速度。

  2. 资源懒加载与请求优化

    • 图片懒加载:只在用户视口范围内加载图片,避免一次性加载所有资源。
    • 合并与压缩文件:将过多的 JS、CSS 文件进行合并与压缩,减少请求数与资源体积。
    • 域名并发优化:浏览器对同一域名的并发请求通常限制在 6 个左右,可以通过配置多个静态资源域名来提升并发度。
  3. 减少 HTTP 请求

    • 将小图标转为 Base64 并内嵌在 HTML/CSS 中,避免额外请求。
    • 使用 图标字体库(IconFont) 代替多张小图片,提升复用性与加载效率。
  4. 开启传输压缩
    启用 GzipBrotli 压缩,将 HTML、CSS、JS 等文本资源进行压缩传输,大幅减少数据体积。

🔍 GET vs POST 深度解析

基础区别对比表

特性GETPOST
用途获取数据提交数据
数据位置URL参数(Query String)请求体(Request Body)
安全性相对不安全(URL可见)相对安全(数据在请求体)
缓存可被缓存通常不被缓存
书签可保存书签无法保存书签
数据长度受URL长度限制(~2048字符)理论上无限制
幂等性幂等(多次调用结果相同)非幂等(可能产生副作用)

详细解析

1. 数据传输方式

GET请求示例:

 1GET /search?q=HTTP&type=article HTTP/1.1
 2Host: www.juejin.cn
 3User-Agent: Mozilla/5.0
 4Accept: text/html

POST请求示例:

 1POST /api/login HTTP/1.1
 2Host: www.juejin.cn
 3Content-Type: application/json
 4Content-Length: 45
 5
 6{
 7  "username": "developer",
 8  "password": "123456"
 9}
2. RESTful API设计
 1GET    /api/users        
 2GET    /api/users/123    
 3POST   /api/users        
 4PUT    /api/users/123    
 5PATCH  /api/users/123    
 6DELETE /api/users/123    
3. 安全性考虑
 1GET /api/login?username=admin&password=123456
 2
 3
 4POST /api/login
 5Content-Type: application/json
 6{
 7  "username": "admin", 
 8  "password": "123456"
 9}
10
11
12HTTPS POST /api/login

面试常见问题解答

Q: GET请求能否包含请求体? A: 技术上可以,但不推荐。RFC 7231没有禁止,但大多数服务器会忽略GET请求的请求体。

Q: POST就一定安全吗? A: 相对安全,但如果没有HTTPS加密,数据在网络传输中仍然是明文,可能被抓包工具截获。

🔒 HTTPS安全机制

HTTPS = HTTP + SSL/TLS

SSL/TLS握手过程
 11. 客户端发送Client Hello
 2   ├── 支持的TLS版本
 3   ├── 支持的加密算法
 4   └── 随机数1
 5
 62. 服务器发送Server Hello
 7   ├── 选择的TLS版本
 8   ├── 选择的加密算法
 9   ├── 随机数2
10   └── 服务器证书
11
123. 客户端验证证书
13   ├── 检查证书有效性
14   ├── 生成预主密钥
15   └── 用服务器公钥加密发送
16
174. 双方生成会话密钥
18   ├── 基于两个随机数和预主密钥
19   └── 开始加密通信
HTTPS优势
  • 数据加密:防止窃听
  • 数据完整性:防止篡改
  • 身份验证:防止冒充
  • SEO友好:搜索引擎优先收录

混合加密原理

 1对称加密 + 非对称加密 = 混合加密
 2
 3┌─────────────────┐    ┌─────────────────┐
 4非对称加密     │    │    对称加密
 5│  (握手阶段)      │ →  │   (数据传输)     │
 6交换密钥       │    │   高效加密
 7└─────────────────┘    └─────────────────┘

🗄️ 浏览器缓存机制

缓存类型

1. 强缓存(Strong Cache)
 1# Expires (HTTP/1.0)
 2Expires: Wed, 21 Oct 2024 07:28:00 GMT
 3
 4# Cache-Control (HTTP/1.1)
 5Cache-Control: max-age=3600
 6Cache-Control: no-cache
 7Cache-Control: no-store
 8Cache-Control: must-revalidate
2. 协商缓存(Negotiation Cache)
 1# 基于修改时间
 2Last-Modified: Wed, 21 Oct 2024 07:28:00 GMT
 3If-Modified-Since: Wed, 21 Oct 2024 07:28:00 GMT
 4
 5# 基于文件内容
 6ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
 7If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

缓存策略最佳实践

 1const cacheStrategies = {
 2  
 3  static: {
 4    'Cache-Control': 'max-age=31536000', 
 5    'Expires': new Date(Date.now() + 31536000000).toUTCString()
 6  },
 7  
 8  
 9  dynamic: {
10    'Cache-Control': 'no-cache', 
11    'ETag': generateETag(content)
12  },
13  
14  
15  sensitive: {
16    'Cache-Control': 'no-store' 
17  }
18};

🌐 TCP/IP协议栈

TCP三次握手

 1客户端                    服务器
 2   |                        |
 3   |  1. SYN(seq=x)        |
 4   |───────────────────────>|
 5   |                        |
 6   |    2. SYN+ACK         |
 7   |<───────────────────────|
 8   |    (seq=y, ack=x+1)   |
 9   |                        |
10   |  3. ACK(ack=y+1)      |
11   |───────────────────────>|
12   |                        |
13   |   连接建立成功          |

TCP四次挥手

 1客户端                    服务器
 2   |                        |
 3   |  1. FIN(seq=u)        |
 4   |───────────────────────>|
 5   |                        |
 6   |  2. ACK(ack=u+1)      |
 7   |<───────────────────────|
 8   |                        |
 9   |  3. FIN(seq=v)        |
10   |<───────────────────────|
11   |                        |
12   |  4. ACK(ack=v+1)      |
13   |───────────────────────>|
14   |                        |
15   |   连接关闭成功          |

TCP vs UDP对比

特性TCPUDP
连接性面向连接无连接
可靠性可靠传输,有确认机制不可靠传输,无确认
速度相对较慢相对较快
头部开销20字节8字节
适用场景文件传输、网页浏览视频直播、DNS查询

📝 面试常见问题集锦

1. HTTP状态码详解

2xx成功
  • 200 OK:请求成功
  • 201 Created:资源创建成功
  • 204 No Content:请求成功但无返回内容
3xx重定向
  • 301 Moved Permanently:永久重定向
  • 302 Found:临时重定向
  • 304 Not Modified:资源未修改,使用缓存
4xx客户端错误
  • 400 Bad Request:请求语法错误
  • 401 Unauthorized:未认证
  • 403 Forbidden:无权限访问
  • 404 Not Found:资源未找到
5xx服务器错误
  • 500 Internal Server Error:服务器内部错误
  • 502 Bad Gateway:网关错误
  • 503 Service Unavailable:服务不可用

2. 高频面试题回答模板

Q1: 描述一下HTTP的发展历程?

参考回答:

HTTP,全称 HyperText Transfer Protocol,作为万维网的基石,它的发展历程大致可以分为以下几个阶段:

1. HTTP/0.9(1991 年)

  • 最初的版本,非常简陋。
  • 只支持 GET 请求,没有请求头和响应头。
  • 返回的内容只能是 纯文本 HTML,无法传输图片、CSS、JS 等资源。
  • 典型应用是传输简单的超文本页面。

2. HTTP/1.0(1996 年)

  • 引入了 请求头(Header) ,开始支持多种数据类型(图片、视频、脚本等)。
  • 支持 状态码缓存机制Content-TypeCookie 等关键功能。
  • 但依然是 短连接:每次请求都要重新建立 TCP 连接,效率低。
  • 特点:丰富了协议功能,但性能不足。

3. HTTP/1.1(1997 年)

  • 是使用最广泛的版本,直到今天很多网站仍在使用。

  • 核心改进

    • 长连接(Connection: keep-alive) :一个 TCP 连接可以复用,避免频繁建立/断开连接。
    • 管道化(Pipelining) :可以一次性发送多个请求,但响应仍需按顺序返回,容易造成队头阻塞。
    • 分块传输(Chunked Transfer Encoding) :支持动态内容分块发送。
    • 更完善的缓存机制(强缓存 + 协商缓存)。
  • 问题:队头阻塞(Head-of-Line Blocking),同一连接上如果前面的响应慢,会阻塞后续请求。


4. HTTP/2(2015 年)

  • 针对 1.1 的性能问题进行优化。

  • 核心特性

    • 二进制分帧:所有请求/响应数据拆成帧,用二进制传输,更高效。
    • 多路复用(Multiplexing) :一个 TCP 连接可以并行传输多个请求和响应,彻底解决了队头阻塞问题。
    • 头部压缩(HPACK) :减少重复 Header 的传输开销。
    • 服务器推送(Server Push) :服务器可主动下发资源(如 CSS、JS),减少首屏延迟。

5. HTTP/3(2019 年,基于 QUIC)

  • 由于 HTTP/2 仍依赖 TCP,而 TCP 的丢包重传机制可能拖慢整个连接,于是引入了 QUIC 协议(基于 UDP)。

  • 优势

    • 真正的多路复用,丢一个包不会阻塞所有请求。
    • 0-RTT 建连,降低握手延迟,提升移动网络下的体验。
    • 内置加密(TLS 1.3),默认更安全。
  • 目前在 YouTube、Google、Facebook 等大型应用已广泛使用

Q2: 如何优化HTTP请求性能?

标准回答:

 1可以从以下几个方面优化
 2
 31. 减少请求次数
 4   - 合并CSS/JS文件
 5   - 使用CSS Sprites
 6   - 内联小图片Base64
 7
 82. 减少请求大小
 9   - 开启Gzip压缩
10   - 压缩图片
11   - 移除无用代码
12
133. 缓存策略
14   - 合理设置Cache-Control
15   - 使用ETags
16   - CDN缓存
17
184. 连接优化
19   - 使用HTTP/2
20   - 域名分片HTTP/1.1
21   - Keep-Alive长连接
22
235. 加载优化
24   - 资源懒加载
25   - 关键资源优先加载
26   - 预加载重要资源
Q3: HTTPS的工作原理?

标准回答:

 1HTTPS = HTTP + SSL/TLS工作流程如下
 2
 31. 握手阶段
 4   - 客户端发送支持的加密算法列表
 5   - 服务器选择算法并发送数字证书
 6   - 客户端验证证书生成对称密钥
 7   - 双方确认开始加密通信
 8
 92. 数据传输
10   - 使用协商好的对称密钥加密数据
11   - 保证数据的机密性完整性身份认证
12
133. 混合加密
14   - 非对称加密交换密钥RSA/ECC
15   - 对称加密传输数据AES
16
17这样既保证了安全性又兼顾了性能

3. 代码实现示例

简单HTTP服务器实现
 1const http = require('http');
 2const url = require('url');
 3
 4const server = http.createServer((req, res) => {
 5  const parsedUrl = url.parse(req.url, true);
 6  const path = parsedUrl.pathname;
 7  const method = req.method;
 8  
 9  
10  res.setHeader('Access-Control-Allow-Origin', '*');
11  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
12  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
13  
14  
15  if (method === 'GET' && path === '/api/users') {
16    res.writeHead(200, { 'Content-Type': 'application/json' });
17    res.end(JSON.stringify({ users: ['Alice', 'Bob'] }));
18  } else if (method === 'POST' && path === '/api/users') {
19    let body = '';
20    req.on('data', chunk => {
21      body += chunk.toString();
22    });
23    req.on('end', () => {
24      const userData = JSON.parse(body);
25      res.writeHead(201, { 'Content-Type': 'application/json' });
26      res.end(JSON.stringify({ message: 'User created', data: userData }));
27    });
28  } else {
29    res.writeHead(404, { 'Content-Type': 'text/plain' });
30    res.end('Not Found');
31  }
32});
33
34server.listen(3000, () => {
35  console.log('Server running on http://localhost:3000');
36});
前端HTTP请求封装
 1class HttpClient {
 2  constructor(baseURL = '') {
 3    this.baseURL = baseURL;
 4    this.interceptors = {
 5      request: [],
 6      response: []
 7    };
 8  }
 9  
10  
11  interceptRequest(fn) {
12    this.interceptors.request.push(fn);
13  }
14  
15  
16  interceptResponse(fn) {
17    this.interceptors.response.push(fn);
18  }
19  
20  async request(config) {
21    
22    for (const interceptor of this.interceptors.request) {
23      config = await interceptor(config);
24    }
25    
26    const { method = 'GET', url, data, headers = {} } = config;
27    const fullUrl = this.baseURL + url;
28    
29    const requestInit = {
30      method,
31      headers: {
32        'Content-Type': 'application/json',
33        ...headers
34      }
35    };
36    
37    if (data && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
38      requestInit.body = JSON.stringify(data);
39    }
40    
41    try {
42      let response = await fetch(fullUrl, requestInit);
43      
44      
45      for (const interceptor of this.interceptors.response) {
46        response = await interceptor(response);
47      }
48      
49      return response;
50    } catch (error) {
51      console.error('HTTP Request failed:', error);
52      throw error;
53    }
54  }
55  
56  get(url, config = {}) {
57    return this.request({ ...config, method: 'GET', url });
58  }
59  
60  post(url, data, config = {}) {
61    return this.request({ ...config, method: 'POST', url, data });
62  }
63  
64  put(url, data, config = {}) {
65    return this.request({ ...config, method: 'PUT', url, data });
66  }
67  
68  delete(url, config = {}) {
69    return this.request({ ...config, method: 'DELETE', url });
70  }
71}
72
73
74const api = new HttpClient('https://api.example.com');
75
76
77api.interceptRequest(async (config) => {
78  const token = localStorage.getItem('token');
79  if (token) {
80    config.headers = {
81      ...config.headers,
82      'Authorization': `Bearer ${token}`
83    };
84  }
85  return config;
86});
87
88
89api.interceptResponse(async (response) => {
90  if (!response.ok) {
91    const errorData = await response.json();
92    throw new Error(errorData.message || 'Request failed');
93  }
94  return response.json();
95});
96
97
98api.get('/users').then(users => console.log(users));
99api.post('/users', { name: 'John', email: 'john@example.com' });

🎯 总结

HTTP协议作为Web开发的基石,掌握其各版本特性、性能优化和安全机制对前端开发者来说至关重要。在面试中,不仅要了解基础概念,更要能够结合实际项目经验,展示对HTTP协议的深入理解。

面试准备建议:

  1. 理论基础要扎实:HTTP各版本特性、TCP/UDP区别、缓存机制
  2. 实践经验要丰富:能结合项目讲述性能优化实践
  3. 前沿技术要了解:HTTP/3、QUIC协议等新技术发展
  4. 问题回答要结构化:先讲原理,再举例子,最后总结
个人笔记记录 2021 ~ 2025