HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的应用层协议,用于客户端和服务器之间的通信。以下是HTTP协议的全面详解:
一、HTTP协议基础
1.1 协议定义
HTTP是一种无状态的、基于请求-响应模式的协议,最初设计用于传输超文本(如HTML文档),现在已支持任意类型的数据传输。
1.2 协议特点
- 无连接:早期版本每次请求建立新连接,HTTP/1.1支持持久连接
- 无状态:服务器不记录客户端状态信息
- 媒体独立:可传输任意类型数据
- 支持C/S架构:客户端-服务器模型
二、HTTP报文结构
2.1 请求报文格式
方法 SP URI SP 协议版本 CRLF
头部字段名: 值 CRLF
...
CRLF
消息体
2.2 响应报文格式
协议版本 SP 状态码 SP 原因短语 CRLF
头部字段名: 值 CRLF
...
CRLF
消息体
三、HTTP方法详解
3.1 主要方法
- GET:获取资源
- POST:提交数据
- PUT:更新完整资源
- DELETE:删除资源
- PATCH:部分更新资源
- HEAD:获取头部信息
- OPTIONS:查询支持的方法
3.2 方法特性对比
|
方法 |
安全 |
幂等 |
缓存 |
消息体 |
|---|---|---|---|---|
|
GET |
是 |
是 |
是 |
无 |
|
POST |
否 |
否 |
部分 |
有 |
|
PUT |
否 |
是 |
否 |
有 |
|
DELETE |
否 |
是 |
否 |
无 |
四、HTTP状态码分类
4.1 状态码范围
- 1xx:信息性状态码
- 2xx:成功状态码
- 3xx:重定向状态码
- 4xx:客户端错误状态码
- 5xx:服务器错误状态码
4.2 常用状态码
- 200 OK:请求成功
- 301 Moved Permanently:永久重定向
- 400 Bad Request:错误请求
- 404 Not Found:资源未找到
- 500 Internal Server Error:服务器内部错误
五、HTTP头部字段
5.1 通用头部字段
- Cache-Control:缓存控制
- Connection:连接管理
- Date:消息创建时间
5.2 请求头部字段
- Accept:可接受的媒体类型
- Authorization:认证信息
- User-Agent:客户端信息
5.3 响应头部字段
- Server:服务器信息
- Set-Cookie:设置Cookie
- Location:重定向目标
六、HTTP版本演进
6.1 HTTP/0.9
- 简单协议,只支持GET方法
- 无头部字段,无状态码
6.2 HTTP/1.0
- 引入方法、状态码、头部字段
- 每次请求建立新连接
6.3 HTTP/1.1(当前主流)
- 持久连接
- 管道化
- 分块传输编码
- 缓存优化
6.4 HTTP/2
- 二进制分帧
- 多路复用
- 头部压缩
- 服务器推送
6.5 HTTP/3
- 基于QUIC协议(UDP)
- 改进连接建立
- 更好的移动网络支持
七、HTTPS安全传输
HTTPS = HTTP + SSL/TLS,提供:
- 数据加密
- 身份验证
- 数据完整性保护
八、Cookie和Session
8.1 Cookie机制
- 服务器通过Set-Cookie头部设置
- 客户端自动在请求中携带Cookie
- 用于状态保持
8.2 Session机制
- 服务器端存储用户状态
- 通过Session ID标识
九、缓存机制
9.1 强缓存
- Expires:绝对过期时间
- Cache-Control:缓存控制策略
9.2 协商缓存
- Last-Modified / If-Modified-Since
- ETag / If-None-Match
十、内容协商
客户端和服务器通过以下头部进行内容协商:
- Accept:客户端接受的媒体类型•
-
Accept-Encoding:内容编码
- Accept-Language:语言偏好
完整示例代码
以下是展示HTTP协议核心概念的完整Python实现:
HTTP协议演示服务器
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
import urllib.parse
class RESTfulHandler(BaseHTTPRequestHandler):
"""RESTful API HTTP服务器"""
# 模拟数据库
users = [
{"id": 1, "name": "Alice", "email": "alice@example.com"},
{"id": 2, "name": "Bob", "email": "bob@example.com"}
]
def _set_headers(self, content_type='application/json'):
"""设置HTTP响应头"""
self.send_response(200)
self.send_header('Content-type', content_type)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
self.end_headers()
def _send_json_response(self, data, status_code=200):
"""发送JSON格式响应"""
self.send_response(status_code)
self.send_header('Content-type', 'application/json')
self.send_header('Access-Control-Allow-Origin', '*')
self.end_headers()
self.wfile.write(json.dumps(data).encode('utf-8'))
def _parse_post_data(self):
"""解析POST请求数据"""
print(self.headers)
print(self.rfile)
content_length = int(self.headers.get('Content-Length', 0))
if content_length == 0:
return {}
post_data = self.rfile.read(content_length)
content_type = self.headers.get('Content-Type', '')
if 'application/json' in content_type:
return json.loads(post_data.decode('utf-8'))
elif 'application/x-www-form-urlencoded' in content_type:
return dict(urllib.parse.parse_qsl(post_data.decode('utf-8')))
else:
# 默认尝试解析为JSON
try:
return json.loads(post_data.decode('utf-8'))
except:
return {'raw_data': post_data.decode('utf-8')}
def do_OPTIONS(self):
"""处理OPTIONS请求(CORS预检)"""
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', 'Content-Type')
self.end_headers()
def do_GET(self):
"""处理GET请求"""
if self.path == '/users' or self.path == '/users/':
# 返回用户列表
self._send_json_response({
"status": "success",
"data": self.users,
"count": len(self.users)
})
elif self.path.startswith('/users/'):
# 获取特定用户
try:
user_id = int(self.path.split('/')[-1])
user = next((u for u in self.users if u['id'] == user_id), None)
if user:
self._send_json_response({
"status": "success",
"data": user
})
else:
self._send_json_response({
"status": "error",
"message": f"User {user_id} not found"
}, 404)
except ValueError:
self._send_json_response({
"status": "error",
"message": "Invalid user ID"
}, 400)
elif self.path == '/':
# 根路径返回API信息
self._send_json_response({
"message": "RESTful API Server",
"version": "1.0",
"endpoints": {
"GET /users": "获取用户列表",
"GET /users/{id}": "获取特定用户",
"POST /users": "创建新用户"
}
})
else:
# 404 Not Found
self._send_json_response({
"status": "error",
"message": f"Endpoint {self.path} not found"
}, 404)
def do_POST(self):
"""处理POST请求"""
if self.path == '/users' or self.path == '/users/':
# 创建新用户
try:
post_data = self._parse_post_data()
if not post_data or 'name' not in post_data:
self._send_json_response({
"status": "error",
"message": "Name field is required"
}, 400)
return
# 生成新用户ID
new_id = max(user['id'] for user in self.users) + 1 if self.users else 1
new_user = {
"id": new_id,
"name": post_data['name'],
"email": post_data.get('email', f"user{new_id}@example.com")
}
self.users.append(new_user)
self._send_json_response({
"status": "success",
"message": "User created successfully",
"data": new_user
}, 201) # 201 Created
except Exception as e:
self._send_json_response({
"status": "error",
"message": f"Error creating user: {str(e)}"
}, 500)
else:
self._send_json_response({
"status": "error",
"message": f"Endpoint {self.path} not found"
}, 404)
def log_message(self, format, *args):
"""自定义日志格式"""
print(f"[{self.log_date_time_string()}] {format % args}")
def run_server(port=5000):
"""启动HTTP服务器"""
server_address = ('', port)
httpd = HTTPServer(server_address, RESTfulHandler)
print(f"🚀 HTTP服务器启动成功!")
print(f"📡 服务地址: http://localhost:{port}")
print(f"🔗 可用端点:")
print(f" GET http://localhost:{port}/users")
print(f" POST http://localhost:{port}/users")
print(f" GET http://localhost:{port}/users/1")
print(f"⏹️ 按 Ctrl+C 停止服务器")
try:
httpd.serve_forever()
except KeyboardInterrupt:
print("\n🛑 服务器已停止")
if __name__ == '__main__':
run_server(5000)
HTTP客户端测试工具
import requests
import json
import sys
def print_debug_info(response):
"""打印详细的调试信息"""
print("\n===== 调试信息 =====")
print(f"请求URL: {response.url}")
print(f"状态码: {response.status_code}")
print("响应头:")
for key, value in response.headers.items():
print(f" {key}: {value}")
content_type = response.headers.get('Content-Type', '').lower()
content_length = int(response.headers.get('Content-Length', 0))
print(f"\n内容类型: {content_type}")
print(f"内容长度: {content_length}字节")
# 安全地打印响应内容的前200个字符
try:
content_preview = response.text[:200]
print(f"\n响应内容预览:")
print(content_preview)
except Exception as e:
print(f"无法读取响应内容: {str(e)}")
print("="*30 + "\n")
def test_get():
"""测试GET请求"""
try:
url = 'http://127.0.0.1:5000/users'
print(f"发送GET请求到: {url}")
response = requests.get(url)
# 打印调试信息
print_debug_info(response)
# 检查响应状态码
if response.status_code != 200:
print(f"错误: 服务器返回状态码 {response.status_code}")
return
# 检查内容类型是否为JSON
content_type = response.headers.get('Content-Type', '').lower()
if 'application/json' not in content_type:
print(f"警告: 响应内容类型不是JSON ({content_type})")
# 尝试解析JSON
try:
data = response.json()
print(f"GET成功! 数据: {json.dumps(data, indent=2)}")
except json.JSONDecodeError as e:
print(f"JSON解析错误: {str(e)}")
print("尝试将响应作为文本处理...")
print(f"响应文本: {response.text[:500]}") # 限制输出长度
except requests.exceptions.RequestException as e:
print(f"请求异常: {str(e)}")
def test_post():
"""测试POST请求(JSON数据)"""
try:
url = 'http://127.0.0.1:5000/users'
data = {"name": "Bob"}
print(f"发送POST请求到: {url}, 数据: {json.dumps(data)}")
response = requests.post(url, json=data)
# 打印调试信息
print_debug_info(response)
# 检查响应状态码
if response.status_code not in [200, 201]:
print(f"错误: 服务器返回状态码 {response.status_code}")
return
# 尝试解析JSON
try:
response_data = response.json()
print(f"POST成功! 响应: {json.dumps(response_data, indent=2)}")
except json.JSONDecodeError as e:
print(f"JSON解析错误: {str(e)}")
print(f"响应文本: {response.text[:500]}")
except requests.exceptions.RequestException as e:
print(f"请求异常: {str(e)}")
def test_post_form():
"""测试POST请求(表单数据)"""
try:
url = 'http://127.0.0.1:5000'
data = {"key": "value"}
print(f"发送表单POST请求到: {url}, 数据: {data}")
response = requests.post(url, data=data)
# 打印调试信息
print_debug_info(response)
# 检查响应状态码
if response.status_code != 200:
print(f"错误: 服务器返回状态码 {response.status_code}")
return
print(f"表单POST响应: {response.text[:500]}")
except requests.exceptions.RequestException as e:
print(f"请求异常: {str(e)}")
if __name__ == '__main__':
print("===== 开始HTTP客户端测试 =====")
test_get()
test_post()
#test_get()
#test_post_form()
print("===== 测试完成 =====")
关键特性说明
1. RESTful API设计
- 资源导向的URL设计
- 标准HTTP方法使用
- 合适的HTTP状态码返回
2. 内容协商支持
- JSON数据格式
- 正确的Content-Type头部
- 字符编码处理
3. 缓存控制
- Cache-Control头部设置
- 适当的缓存策略
4. 错误处理
- 详细的错误信息
- 合适的HTTP状态码
- 一致的错误响应格式
5. CORS支持
- OPTIONS方法处理
- 跨域请求头设置
5094

被折叠的 条评论
为什么被折叠?



