1. HTTP协议基础概念HTTPHyperText Transfer Protocol超文本传输协议是互联网上应用最为广泛的一种网络协议。作为Web的基础它定义了客户端和服务器之间通信的规则。我第一次接触HTTP是在2005年调试一个网站表单提交问题时当时用Wireshark抓包看到了这些神秘的文本数据从此对这个明文协议产生了浓厚兴趣。HTTP本质上是一种无状态的请求-响应协议。客户端通常是浏览器向服务器发送请求服务器处理请求后返回响应。这种简单模型支撑起了整个Web的运转。有趣的是HTTP最初的设计目标只是用来传输HTML文档但随着发展现在可以传输任意类型的数据。协议版本演进HTTP/0.91991年最原始版本只有GET方法HTTP/1.01996年RFC 1945正式标准化增加了HEAD、POST等方法HTTP/1.11997年RFC 2068当前主流版本持久连接、管道化等优化HTTP/22015年RFC 7540二进制协议多路复用等重大改进HTTP/32022年RFC 9114基于QUIC协议解决队头阻塞问题提示虽然HTTP/2和HTTP/3已经发布但HTTP/1.1仍然是目前最广泛支持的版本理解其报文格式对调试网络问题至关重要。2. HTTP报文整体结构HTTP报文就像传统信件的格式分为信封和内容两部分。具体来说一个完整的HTTP报文由以下部分组成2.1 起始行Start Line位于报文的第一行分为请求报文中的请求行Request Line响应报文中的状态行Status Line2.2 头部字段Headers由多行key-value对组成每行以回车换行CRLF即\r\n结束。头部字段结束后需要有一个空行即连续两个CRLF作为分隔。2.3 消息正文Body可选部分包含实际传输的数据。可以是文本、图片、视频等各种格式。一个典型的HTTP请求报文示例GET /index.html HTTP/1.1 Host: www.example.com User-Agent: Mozilla/5.0 Accept: text/html [空行] [此处是body本例中没有]3. 请求报文详解3.1 请求行结构请求行由三部分组成格式为方法 请求目标 协议版本例如GET /about HTTP/1.13.1.1 请求方法HTTP/1.1定义了8种方法最常用的是GET获取资源POST提交数据PUT上传资源DELETE删除资源HEAD类似GET但只返回头部OPTIONS查询服务器支持的方法3.1.2 请求目标通常是URI的路径部分如/index.html。在代理请求时可能是完整URL。3.1.3 协议版本如HTTP/1.0或HTTP/1.1。这会影响服务器处理请求的方式。3.2 常见请求头字段头字段说明示例Host服务器域名Host: example.comUser-Agent客户端信息User-Agent: Mozilla/5.0Accept可接受的响应类型Accept: text/htmlAccept-Language首选语言Accept-Language: en-USConnection连接控制Connection: keep-aliveContent-Type请求体的MIME类型Content-Type: application/jsonContent-Length请求体长度Content-Length: 3484. 响应报文详解4.1 状态行结构状态行也由三部分组成协议版本 状态码 原因短语例如HTTP/1.1 200 OK4.1.1 状态码分类状态码是三位数字分为五类1xx信息性状态码2xx成功状态码如200 OK3xx重定向状态码如301 Moved Permanently4xx客户端错误状态码如404 Not Found5xx服务器错误状态码如500 Internal Server Error4.1.2 常见状态码200 OK请求成功301 Moved Permanently永久重定向304 Not Modified资源未修改400 Bad Request错误请求403 Forbidden禁止访问404 Not Found资源不存在500 Internal Server Error服务器内部错误502 Bad Gateway网关错误4.2 常见响应头字段头字段说明示例Server服务器信息Server: nginx/1.18.0Date响应时间Date: Mon, 27 Jun 2022 12:28:53 GMTContent-Type响应体的MIME类型Content-Type: text/html; charsetutf-8Content-Length响应体长度Content-Length: 1024Cache-Control缓存控制Cache-Control: max-age3600Set-Cookie设置CookieSet-Cookie: sessionid12345; Path/5. HTTP报文实战分析5.1 使用开发者工具查看现代浏览器都内置了开发者工具可以方便地查看HTTP报文Chrome中按F12打开开发者工具切换到Network标签页刷新页面查看所有请求点击某个请求查看详情5.2 使用cURL命令cURL是一个强大的命令行工具可以用来发送HTTP请求curl -v http://example.com-v参数会显示详细的请求和响应信息。5.3 常见问题排查400 Bad Request通常是因为请求报文格式错误如头部字段格式不正确403 Forbidden检查服务器权限设置404 Not Found确认请求路径是否正确500 Internal Server Error查看服务器日志定位问题502 Bad Gateway通常是上游服务器无响应注意在实际开发中502错误经常出现在微服务架构中当某个服务不可达时API网关就会返回这个状态码。这时需要检查服务是否正常运行网络连接是否通畅。6. HTTP与HTTPS的区别虽然本文主要讨论HTTP但有必要简要提及其安全版本HTTPSHTTPS HTTP SSL/TLS加密默认端口HTTP是80HTTPS是443HTTPS提供数据加密身份认证数据完整性保护现代网站都应该使用HTTPS7. 高级话题7.1 持久连接HTTP/1.1默认使用持久连接Connection: keep-alive可以在一个TCP连接上发送多个HTTP请求/响应减少建立连接的开销。7.2 分块传输编码当响应体长度未知时可以使用Transfer-Encoding: chunked将数据分成多个块传输。7.3 内容协商通过Accept-*系列头部字段客户端可以声明自己的偏好服务器根据这些信息返回最合适的内容。7.4 CORS跨域现代浏览器出于安全考虑会限制跨域请求需要通过特定的头部字段如Access-Control-Allow-Origin来控制。8. 实际开发建议始终设置Content-Type头部明确指定内容类型和编码对敏感操作使用POST而非GET因为GET参数会出现在URL中合理使用缓存控制头提高性能对API响应使用标准状态码方便客户端处理考虑使用HTTPS保护数据传输安全在开发RESTful API时正确使用HTTP方法和状态码我在实际项目中遇到过很多因HTTP报文格式不正确导致的问题。有一次一个同事在头部字段的冒号后多加了一个空格导致服务器返回400错误我们花了两个小时才找到这个微小但关键的问题。从那以后我对HTTP报文的格式要求变得格外严格。