HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最广泛的协议之一,是Web开发的基础。我们每天浏览网页、调用API、上传下载文件,都是在使用HTTP协议。但是,很多人对HTTP协议的了解只停留在"输入网址就能打开网页"的层面,对HTTP协议的工作原理、请求响应结构、状态码、头部字段等了解不多。

作为程序员,深入理解HTTP协议是非常重要的,它能帮助我们更好地开发Web应用,排查网络问题,优化网站性能。今天就来详细讲解HTTP协议,从请求到响应,带大家全面了解这个互联网的基础协议。

HTTP协议简介

1. 什么是HTTP协议: HTTP是超文本传输协议,是一种用于传输超文本(如HTML、图片、视频等)的应用层协议。它基于TCP/IP协议,默认使用80端口(HTTPS默认使用443端口)。HTTP是无状态协议,服务器不会保存客户端的状态,每次请求都是独立的。

2. HTTP协议的历史

  • HTTP/0.9(1991年):最初版本,只有GET方法,没有头部,只能传输HTML
  • HTTP/1.0(1996年):增加了POST、HEAD方法,增加了头部字段和状态码,支持传输多种内容类型
  • HTTP/1.1(1999年):目前最广泛使用的版本,增加了持久连接、管道化、分块传输、缓存控制、内容协商等
  • HTTP/2(2015年):新一代HTTP协议,支持多路复用、头部压缩、服务器推送、二进制帧,性能更好
  • HTTP/3(2022年正式标准化):基于QUIC协议,使用UDP替代TCP,解决了TCP队头阻塞问题,性能更好

3. HTTP协议的特点

  • 基于请求-响应模型:客户端发送请求,服务器返回响应
  • 无状态:服务器不保存客户端的状态,每次请求都是独立的
  • 可扩展:通过头部字段可以扩展功能
  • 灵活:可以传输任意类型的数据(通过Content-Type指定)
  • 简单快速:协议简单,通信速度快

HTTP请求结构

HTTP请求由三部分组成:请求行、请求头部、请求体。

1. 请求行: 请求行是请求的第一行,包含请求方法、请求URL、HTTP版本。

GET /index.html HTTP/1.1
  • GET:请求方法
  • /index.html:请求URL
  • HTTP/1.1:HTTP版本

2. 请求方法: HTTP定义了多种请求方法,常用的有:

  • GET:获取资源,请求指定的页面信息,并返回实体主体
  • POST:提交数据,向指定资源提交数据进行处理请求(如提交表单、上传文件)
  • PUT:上传文件,向指定资源位置上传其最新内容
  • DELETE:删除资源,请求服务器删除指定的页面
  • HEAD:获取头部,类似于GET请求,只不过返回的响应中没有具体的内容,用于获取报头
  • OPTIONS:获取选项,返回服务器支持的HTTP方法
  • PATCH:部分更新,对资源进行部分修改

GET和POST的区别:

  • GET参数在URL中,POST参数在请求体中
  • GET有长度限制(URL长度限制),POST没有长度限制
  • GET可以被缓存,POST不能被缓存
  • GET可以被收藏为书签,POST不能
  • GET只用于获取数据,POST用于提交数据
  • GET是幂等的(多次请求结果相同),POST不是幂等的

3. 请求URL: URL(Uniform Resource Locator,统一资源定位符)用于定位互联网上的资源。

https://www.example.com:443/path/to/page?query=value#fragment
  • https:协议
  • www.example.com:域名
  • 443:端口
  • /path/to/page:路径
  • ?query=value:查询参数
  • #fragment:片段(锚点,不会发送到服务器)

4. 请求头部: 请求头部包含了客户端的环境信息、请求参数等。每行一个头部,格式为字段名: 值

Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Cookie: sessionid=abc123; username=test
Referer: https://www.google.com/

常用请求头部:

  • Host:目标主机和端口
  • User-Agent:客户端信息(浏览器、操作系统等)
  • Accept:客户端能接受的内容类型
  • Accept-Language:客户端能接受的语言
  • Accept-Encoding:客户端能接受的编码(压缩方式)
  • Connection:连接方式(keep-alive持久连接,close关闭连接)
  • Cookie:客户端发送的Cookie
  • Referer:请求来源页面
  • Content-Type:请求体的内容类型(POST请求时使用)
  • Content-Length:请求体的长度
  • Authorization:认证信息
  • Cache-Control:缓存控制

5. 请求体: 请求体是请求的数据部分,GET请求通常没有请求体,POST、PUT等请求有请求体。请求体的格式由Content-Type指定。

常见的请求体格式:

  • application/x-www-form-urlencoded:表单格式,key1=value1&key2=value2
  • multipart/form-data:多部分格式,用于上传文件
  • application/json:JSON格式,{"key1":"value1","key2":"value2"}
  • text/plain:纯文本格式
  • application/xml:XML格式

HTTP响应结构

HTTP响应也由三部分组成:状态行、响应头部、响应体。

1. 状态行: 状态行是响应的第一行,包含HTTP版本、状态码、状态描述。

HTTP/1.1 200 OK
  • HTTP/1.1:HTTP版本
  • 200:状态码
  • OK:状态描述

2. 状态码: 状态码是服务器对请求的响应状态,分为5类:

  • 1xx:信息,请求已接收,继续处理
  • 2xx:成功,请求已成功被接收、理解、接受
  • 3xx:重定向,需要进一步操作以完成请求
  • 4xx:客户端错误,请求有语法错误或请求无法实现
  • 5xx:服务器错误,服务器未能实现合法的请求

常用状态码:

  • 200 OK:请求成功
  • 201 Created:资源创建成功
  • 204 No Content:请求成功,但没有返回内容
  • 301 Moved Permanently:永久重定向
  • 302 Found:临时重定向
  • 304 Not Modified:资源未修改,使用缓存
  • 400 Bad Request:请求语法错误
  • 401 Unauthorized:未授权,需要认证
  • 403 Forbidden:禁止访问
  • 404 Not Found:资源不存在
  • 405 Method Not Allowed:请求方法不允许
  • 500 Internal Server Error:服务器内部错误
  • 502 Bad Gateway:网关错误
  • 503 Service Unavailable:服务不可用
  • 504 Gateway Timeout:网关超时

3. 响应头部: 响应头部包含了服务器的信息、响应参数等。

Server: nginx/1.18.0
Date: Tue, 20 Apr 2016 12:00:00 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 1234
Content-Encoding: gzip
Connection: keep-alive
Cache-Control: max-age=3600
ETag: "abc123"
Last-Modified: Mon, 19 Apr 2016 10:00:00 GMT
Set-Cookie: sessionid=xyz789; Path=/; HttpOnly
Location: https://www.example.com/new-page

常用响应头部:

  • Server:服务器信息
  • Date:响应时间
  • Content-Type:响应体的内容类型和编码
  • Content-Length:响应体的长度
  • Content-Encoding:响应体的编码(压缩方式)
  • Connection:连接方式
  • Cache-Control:缓存控制
  • ETag:资源标识,用于缓存验证
  • Last-Modified:资源最后修改时间
  • Set-Cookie:设置Cookie
  • Location:重定向目标URL(3xx状态码时使用)
  • Access-Control-Allow-Origin:跨域允许的源

4. 响应体: 响应体是服务器返回的数据,可以是HTML、JSON、图片、视频等任意类型的数据,格式由Content-Type指定。

HTTP工作原理

1. 一次完整的HTTP请求过程

  1. 客户端解析URL,获取域名、端口、路径等
  2. 客户端通过DNS解析域名,获取服务器IP地址
  3. 客户端与服务器建立TCP连接(三次握手)
  4. 客户端发送HTTP请求
  5. 服务器接收请求,处理请求
  6. 服务器返回HTTP响应
  7. 客户端接收响应,解析响应
  8. 关闭TCP连接(或保持连接用于后续请求)

2. 持久连接: HTTP/1.1默认使用持久连接(Keep-Alive),即一次TCP连接可以处理多个HTTP请求,不需要每次请求都建立新的TCP连接。这样可以减少TCP连接建立和关闭的开销,提高性能。

Connection: keep-alive

3. 管道化: HTTP/1.1支持管道化(Pipelining),即客户端可以在一个TCP连接上连续发送多个请求,不需要等待前一个请求的响应。但是服务器必须按请求的顺序返回响应,所以可能会有队头阻塞问题。HTTP/2通过多路复用解决了这个问题。

4. 无状态与Cookie/Session: HTTP是无状态协议,服务器不会保存客户端的状态。但是很多应用需要保存用户状态(如登录状态),这就需要使用Cookie和Session。

  • Cookie:服务器通过Set-Cookie头部设置Cookie,浏览器保存Cookie,后续请求自动带上Cookie。Cookie存储在客户端,有大小和数量限制。
  • Session:服务器端保存用户状态,通过Cookie中的Session ID关联用户。Session存储在服务器端,没有大小限制,但是需要占用服务器资源。

HTTPS协议

HTTPS(HTTP Secure)是HTTP的安全版本,在HTTP的基础上加入了SSL/TLS加密层,保证数据传输的安全性。

1. HTTPS的作用

  • 加密:数据传输过程中加密,防止被窃听
  • 认证:验证服务器身份,防止被冒充
  • 完整性:保证数据在传输过程中不被篡改

2. HTTPS的工作原理

  1. 客户端与服务器建立TCP连接
  2. SSL/TLS握手:

- 客户端发送支持的加密算法列表 - 服务器选择加密算法,返回数字证书 - 客户端验证证书,生成预主密钥,用服务器公钥加密后发送 - 双方根据预主密钥生成会话密钥

  1. 使用会话密钥加密HTTP请求和响应

3. HTTPS vs HTTP

  • HTTPS默认端口443,HTTP默认端口80
  • HTTPS需要SSL证书,HTTP不需要
  • HTTPS数据加密,HTTP明文传输
  • HTTPS性能略低(加密解密开销),但是HTTP/2通常只在HTTPS下使用
  • HTTPS更安全,有利于SEO(搜索引擎优先收录HTTPS网站)

HTTP缓存

HTTP缓存是优化网站性能的重要手段,通过缓存可以减少重复请求,加快页面加载速度。

1. 缓存控制头部

  • Cache-Control:缓存控制,常用值有:

- max-age=3600:缓存有效期3600秒 - no-cache:可以缓存,但是使用前需要验证 - no-store:不缓存 - public:可以被任何缓存(包括CDN)缓存 - private:只能被客户端缓存

  • Expires:缓存过期时间(HTTP/1.0的方式,优先级低于Cache-Control)
  • ETag:资源标识,用于缓存验证
  • Last-Modified:资源最后修改时间,用于缓存验证

2. 缓存验证: 当缓存过期后,客户端会向服务器发送验证请求:

  • If-None-Match:带上之前的ETag值,如果服务器资源未修改,返回304 Not Modified,使用缓存
  • If-Modified-Since:带上之前的Last-Modified时间,如果服务器资源未修改,返回304 Not Modified,使用缓存

3. 强缓存 vs 协商缓存

  • 强缓存:缓存未过期时,直接使用缓存,不向服务器发送请求。由Cache-Control和Expires控制。
  • 协商缓存:缓存过期后,向服务器发送验证请求,服务器判断资源是否修改,如果未修改返回304,使用缓存;如果修改返回200和新资源。由ETag/If-None-Match和Last-Modified/If-Modified-Since控制。

跨域与CORS

1. 什么是跨域: 跨域是指浏览器从一个域名的网页去请求另一个域名的资源。浏览器的同源策略限制了跨域请求,只有协议、域名、端口都相同才是同源。

2. CORS(跨域资源共享): CORS是一种跨域解决方案,通过服务器设置响应头部,允许浏览器跨域请求。

常用CORS头部:

  • Access-Control-Allow-Origin:允许的源,*表示允许所有源
  • Access-Control-Allow-Methods:允许的请求方法
  • Access-Control-Allow-Headers:允许的请求头部
  • Access-Control-Allow-Credentials:是否允许携带Cookie
  • Access-Control-Max-Age:预检请求的缓存时间

3. 简单请求 vs 预检请求

  • 简单请求:GET、HEAD、POST,且Content-Type为application/x-www-form-urlencoded、multipart/form-data、text/plain,直接发送请求
  • 预检请求:非简单请求会先发送OPTIONS预检请求,服务器确认允许后再发送实际请求

HTTP性能优化

1. 减少HTTP请求

  • 合并CSS、JS文件
  • 使用CSS Sprites合并图片
  • 使用内联图片(Base64)
  • 懒加载,延迟加载非首屏资源

2. 使用CDN

  • 静态资源使用CDN加速
  • CDN节点离用户更近,访问速度更快
  • CDN可以缓存静态资源,减轻服务器压力

3. 启用压缩

  • 启用Gzip/Brotli压缩文本资源(HTML、CSS、JS)
  • 图片使用合适的格式(WebP、JPEG、PNG)和压缩
  • 压缩可以大大减少传输数据量,加快加载速度

4. 合理设置缓存

  • 静态资源设置长期缓存(Cache-Control: max-age=31536000)
  • HTML页面设置短期缓存或不缓存
  • 使用文件名哈希(如app.abc123.js)实现缓存更新

5. 使用HTTP/2

  • HTTP/2支持多路复用,一个连接可以并行处理多个请求
  • HTTP/2支持头部压缩,减少头部传输量
  • HTTP/2支持服务器推送,提前推送资源
  • HTTP/2性能比HTTP/1.1好很多

6. 优化DNS解析

  • 使用DNS预解析(<link rel="dns-prefetch" href="//example.com">
  • 使用稳定的DNS服务商
  • 减少域名数量,减少DNS解析

总结

HTTP协议是Web开发的基础,深入理解HTTP协议对程序员非常重要。本文介绍了HTTP协议的基本概念、请求响应结构、工作原理、HTTPS、缓存、跨域、性能优化等内容。

HTTP协议虽然看起来简单,但是细节很多,需要在实际开发中不断学习和实践。希望这篇文章能帮助大家更好地理解HTTP协议,在开发中更好地使用HTTP,排查网络问题,优化网站性能。

HTTP协议还在不断发展,从HTTP/1.1到HTTP/2再到HTTP/3,性能越来越好,功能越来越强大。作为程序员,我们要持续学习,跟上技术的发展,用好HTTP协议,开发出更好的Web应用。