1.http.server #
http.server 是 Python 标准库中的一个模块,提供了实现 HTTP 服务器的基本功能。它主要用于开发测试、教学或快速搭建简单的本地服务器,不适合生产环境使用。
2.核心组件 #
2.1. HTTPServer 类 #
HTTPServer 是主要的服务器类,继承自 socketserver.TCPServer。
主要功能:
- 监听指定端口
- 接收客户端连接
- 将请求分发给处理器(handler)
常用参数:
server_address:元组 (host, port)RequestHandlerClass:处理请求的类(必须继承BaseHTTPRequestHandler)
2.2. BaseHTTPRequestHandler 类 #
这是请求处理器的基类,开发者需要继承此类并实现自己的处理方法。
主要方法:
handle():处理请求的总入口(通常不需要重写)do_GET():处理 GET 请求do_POST():处理 POST 请求do_HEAD():处理 HEAD 请求send_response(code, message=None):发送响应状态码send_header(keyword, value):发送响应头end_headers():结束头部发送wfile:用于写入响应体的文件类对象rfile:用于读取请求体的文件类对象
2.3. ThreadingHTTPServer 类 #
ThreadingHTTPServer 是 http.server 自带的多线程服务器实现(相当于将 ThreadingMixIn 与 HTTPServer 组合的快捷版本)。它会为每个进入的请求创建一个新线程进行处理,从而在 I/O 密集型场景(例如磁盘读写、网络等待)下提升并发能力。
适用场景:
- 本地开发/教学中需要同时处理多个请求的简单服务
- I/O 密集型处理(例如慢速响应、模拟延迟)
注意事项:
- 受 GIL 影响,多线程对 CPU 密集型任务的收益有限
- 同一进程内共享状态需考虑线程安全(加锁/无共享/使用线程安全容器)
- 接口签名与
HTTPServer基本一致,直接替换即可:ThreadingHTTPServer(server_address, RequestHandlerClass)
3.基础示例 #
# 导入必要的模块
from http.server import HTTPServer, BaseHTTPRequestHandler
# 定义简单的HTTP请求处理器类
class SimpleHandler(BaseHTTPRequestHandler):
# 处理GET请求的方法
def do_GET(self):
# 发送HTTP 200状态码
self.send_response(200)
# 设置响应内容类型为HTML
self.send_header('Content-type', 'text/html')
# 结束头部发送
self.end_headers()
# 获取客户端请求的路径
path = self.path
# 创建HTML响应内容
html_content = f"""
<html>
<head><title>简单服务器</title></head>
<body>
<h1>来自Python的问候!</h1>
<p>您请求的路径是: {path}</p>
</body>
</html>
"""
# 将HTML内容编码为UTF-8字节并写入响应
self.wfile.write(html_content.encode('utf-8'))
# 定义服务器地址和端口
server_address = ('', 8000) # 空字符串表示监听所有可用接口
# 创建HTTP服务器实例
httpd = HTTPServer(server_address, SimpleHandler)
# 打印服务器启动信息
print("服务器运行在 http://localhost:8000")
# 启动服务器,永久运行
httpd.serve_forever()4.高级特性 #
4.1. 处理 POST 请求 #
# 导入必要的模块
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
# 定义支持POST请求的处理器类
class PostHandler(BaseHTTPRequestHandler):
# 处理GET请求的方法
def do_GET(self):
# 发送HTTP 200状态码
self.send_response(200)
# 设置响应内容类型为HTML
self.send_header('Content-type', 'text/html')
# 结束头部发送
self.end_headers()
# 创建包含表单的HTML页面
html_content = """
<html>
<head><title>POST测试</title></head>
<body>
<h1>POST请求测试</h1>
<form method="POST">
<input type="text" name="message" placeholder="请输入消息">
<button type="submit">发送</button>
</form>
</body>
</html>
"""
# 将HTML内容编码并写入响应
self.wfile.write(html_content.encode('utf-8'))
# 处理POST请求的方法
def do_POST(self):
# 获取请求体的长度
content_length = int(self.headers['Content-Length'])
# 读取POST数据
post_data = self.rfile.read(content_length)
# 发送HTTP 200状态码
self.send_response(200)
# 设置响应内容类型为JSON
self.send_header('Content-type', 'application/json')
# 结束头部发送
self.end_headers()
# 创建响应数据字典
response = {
'status': '成功',
'received_data': post_data.decode('utf-8')
}
# 将响应数据转换为JSON并编码写入
self.wfile.write(json.dumps(response).encode('utf-8'))
# 定义服务器地址和端口
server_address = ('', 8000)
# 创建HTTP服务器实例
httpd = HTTPServer(server_address, PostHandler)
# 打印服务器启动信息
print("POST服务器运行在 http://localhost:8000")
# 启动服务器
httpd.serve_forever()4.2. 处理不同的路径 #
# 导入必要的模块
from http.server import HTTPServer, BaseHTTPRequestHandler
# 定义多路径处理器类
class MultiPathHandler(BaseHTTPRequestHandler):
# 处理GET请求的方法
def do_GET(self):
# 根据请求路径分发到不同的处理方法
if self.path == '/':
# 处理首页请求
self.handle_homepage()
elif self.path == '/about':
# 处理关于页面请求
self.handle_about()
else:
# 处理404页面请求
self.handle_not_found()
# 处理首页的方法
def handle_homepage(self):
# 发送HTTP 200状态码
self.send_response(200)
# 设置响应内容类型为HTML
self.send_header('Content-type', 'text/html')
# 结束头部发送
self.end_headers()
# 首页HTML内容
html_content = """
<html>
<head><title>首页</title></head>
<body>
<h1>欢迎来到首页</h1>
<p><a href="/about">关于我们</a></p>
</body>
</html>
"""
# 将HTML内容编码并写入响应
self.wfile.write(html_content.encode('utf-8'))
# 处理关于页面的方法
def handle_about(self):
# 发送HTTP 200状态码
self.send_response(200)
# 设置响应内容类型为HTML
self.send_header('Content-type', 'text/html')
# 结束头部发送
self.end_headers()
# 关于页面HTML内容
html_content = """
<html>
<head><title>关于我们</title></head>
<body>
<h1>关于我们</h1>
<p>这是一个使用Python http.server模块创建的简单网站。</p>
<p><a href="/">返回首页</a></p>
</body>
</html>
"""
# 将HTML内容编码并写入响应
self.wfile.write(html_content.encode('utf-8'))
# 处理404页面的方法
def handle_not_found(self):
# 发送HTTP 404状态码
self.send_response(404)
# 设置响应内容类型为HTML
self.send_header('Content-type', 'text/html')
# 结束头部发送
self.end_headers()
# 404页面HTML内容
html_content = """
<html>
<head><title>页面未找到</title></head>
<body>
<h1>404 - 页面未找到</h1>
<p>抱歉,您请求的页面不存在。</p>
<p><a href="/">返回首页</a></p>
</body>
</html>
"""
# 将HTML内容编码并写入响应
self.wfile.write(html_content.encode('utf-8'))
# 定义服务器地址和端口
server_address = ('', 8000)
# 创建HTTP服务器实例
httpd = HTTPServer(server_address, MultiPathHandler)
# 打印服务器启动信息
print("多路径服务器运行在 http://localhost:8000")
# 启动服务器
httpd.serve_forever()4.3. 服务静态文件 #
# 导入必要的模块
from http.server import HTTPServer, BaseHTTPRequestHandler
import os
# 定义静态文件处理器类
class StaticFileHandler(BaseHTTPRequestHandler):
# 处理GET请求的方法
def do_GET(self):
try:
# 安全地处理路径,防止目录遍历攻击
# 移除查询参数和锚点
path = self.path.split('?', 1)[0].split('#', 1)[0]
# 如果路径是根目录,默认提供index.html
if path == '/':
path = '/index.html'
# 从当前目录下的static文件夹提供服务
# 移除路径开头的斜杠并拼接static目录
full_path = os.path.join('static', path.lstrip('/'))
# 检查文件是否存在
if not os.path.exists(full_path):
raise FileNotFoundError
# 以二进制模式打开文件
with open(full_path, 'rb') as file:
# 发送HTTP 200状态码
self.send_response(200)
# 根据文件扩展名设置Content-type
ext = os.path.splitext(full_path)[1]
content_type = self.guess_type(ext)
self.send_header('Content-type', content_type)
# 结束头部发送
self.end_headers()
# 读取文件内容并写入响应
self.wfile.write(file.read())
except FileNotFoundError:
# 文件不存在时发送404错误
self.send_error(404, 'File Not Found')
# 根据文件扩展名猜测MIME类型的方法
def guess_type(self, ext):
# 定义常见文件扩展名对应的MIME类型
mime_types = {
'.html': 'text/html',
'.css': 'text/css',
'.js': 'application/javascript',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.ico': 'image/x-icon',
'.txt': 'text/plain',
'.json': 'application/json',
}
# 返回对应的MIME类型,默认为二进制流
return mime_types.get(ext.lower(), 'application/octet-stream')
# 定义服务器地址和端口
server_address = ('', 8000)
# 创建HTTP服务器实例
httpd = HTTPServer(server_address, StaticFileHandler)
# 打印服务器启动信息
print("静态文件服务器运行在 http://localhost:8000")
print("请确保在项目根目录下创建static文件夹并放入文件")
# 启动服务器
httpd.serve_forever()4.4. 使用 ThreadingHTTPServer 处理并发请求 #
本小节演示如何直接使用 ThreadingHTTPServer 来并发地处理多个请求。示例中处理器会刻意 sleep 两秒,便于通过同时发起多个请求观察并发效果。
# 从 http.server 导入多线程服务器与基类处理器
from http.server import ThreadingHTTPServer, BaseHTTPRequestHandler
# 导入 time 以模拟耗时操作
import time
# 定义一个模拟慢处理的请求处理器类
class SlowHandler(BaseHTTPRequestHandler):
# 覆写 GET 方法
def do_GET(self):
# 发送 200 OK 状态码
self.send_response(200)
# 设置响应头为纯文本,UTF-8 编码
self.send_header('Content-Type', 'text/plain; charset=utf-8')
# 结束头部
self.end_headers()
# 模拟耗时(例如外部 I/O),用于观察并发处理
time.sleep(2)
# 写入响应体并结束
self.wfile.write(f'path={self.path}\n'.encode('utf-8'))
# 监听所有网卡的 8001 端口
server_address = ('', 8001)
# 创建多线程 HTTP 服务器实例,传入处理器类
httpd = ThreadingHTTPServer(server_address, SlowHandler)
# 打印启动信息
print('ThreadingHTTPServer 运行在 http://localhost:8001 (每个请求独立线程)')
# 启动服务器主循环
httpd.serve_forever()5.命令行使用 #
Python 内置了一个简单的命令行接口:
# 启动简单服务器(默认端口8000)
python -m http.server
# 指定端口
python -m http.server 8080
# 绑定到特定接口
python -m http.server 8000 --bind 127.0.0.1
# 启用目录列表(默认已启用)
python -m http.server --directory /path/to/serve6.局限性 #
- 单线程:默认情况下是单线程的,不能同时处理多个请求
- 安全性:没有内置的安全功能,不适合暴露在公网
- 功能有限:缺少现代Web框架的路由、模板等高级功能
对于生产环境,建议使用:
- 开发:Flask、Django等框架
- 生产:Nginx、Apache等专业服务器
- ASGI服务器:Uvicorn、Hypercorn等(用于异步应用)
7.扩展建议 #
如果需要更强大的功能但仍想基于http.server构建,可以考虑:
- 使用
ThreadingMixIn实现多线程:
# 导入必要的模块
from http.server import HTTPServer, BaseHTTPRequestHandler
from socketserver import ThreadingMixIn
# 定义多线程HTTP服务器类
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
"""处理每个请求在一个新线程中"""
# 允许服务器重用地址
allow_reuse_address = True
# 定义简单的请求处理器
class SimpleHandler(BaseHTTPRequestHandler):
# 处理GET请求的方法
def do_GET(self):
# 发送HTTP 200状态码
self.send_response(200)
# 设置响应内容类型为HTML
self.send_header('Content-type', 'text/html')
# 结束头部发送
self.end_headers()
# 创建HTML响应内容
html_content = """
<html>
<head><title>多线程服务器</title></head>
<body>
<h1>多线程HTTP服务器</h1>
<p>这个服务器可以同时处理多个请求!</p>
<p>每个请求都会在独立的线程中处理。</p>
</body>
</html>
"""
# 将HTML内容编码并写入响应
self.wfile.write(html_content.encode('utf-8'))
# 定义服务器地址和端口
server_address = ('', 8000)
# 创建多线程HTTP服务器实例
httpd = ThreadedHTTPServer(server_address, SimpleHandler)
# 打印服务器启动信息
print("多线程服务器运行在 http://localhost:8000")
# 启动服务器
httpd.serve_forever()- 添加简单的路由功能:
# 导入必要的模块
from http.server import HTTPServer, BaseHTTPRequestHandler
# 定义首页处理函数
def home_handler(self):
# 发送HTTP 200状态码
self.send_response(200)
# 设置响应内容类型为HTML
self.send_header('Content-type', 'text/html')
# 结束头部发送
self.end_headers()
# 首页HTML内容
html_content = """
<html>
<head><title>首页</title></head>
<body>
<h1>欢迎来到首页</h1>
<p><a href="/about">关于我们</a></p>
</body>
</html>
"""
# 将HTML内容编码并写入响应
self.wfile.write(html_content.encode('utf-8'))
# 定义关于页面处理函数
def about_handler(self):
# 发送HTTP 200状态码
self.send_response(200)
# 设置响应内容类型为HTML
self.send_header('Content-type', 'text/html')
# 结束头部发送
self.end_headers()
# 关于页面HTML内容
html_content = """
<html>
<head><title>关于我们</title></head>
<body>
<h1>关于我们</h1>
<p>这是一个使用路由功能的简单网站。</p>
<p><a href="/">返回首页</a></p>
</body>
</html>
"""
# 将HTML内容编码并写入响应
self.wfile.write(html_content.encode('utf-8'))
# 定义404页面处理函数
def not_found_handler(self):
# 发送HTTP 404状态码
self.send_response(404)
# 设置响应内容类型为HTML
self.send_header('Content-type', 'text/html')
# 结束头部发送
self.end_headers()
# 404页面HTML内容
html_content = """
<html>
<head><title>页面未找到</title></head>
<body>
<h1>404 - 页面未找到</h1>
<p>抱歉,您请求的页面不存在。</p>
<p><a href="/">返回首页</a></p>
</body>
</html>
"""
# 将HTML内容编码并写入响应
self.wfile.write(html_content.encode('utf-8'))
# 定义路由字典
routes = {
'/': home_handler,
'/about': about_handler,
}
# 定义带路由功能的请求处理器类
class RouterHandler(BaseHTTPRequestHandler):
# 处理GET请求的方法
def do_GET(self):
# 从路由字典中获取对应的处理函数
handler = routes.get(self.path, not_found_handler)
# 调用对应的处理函数
handler(self)
# 定义服务器地址和端口
server_address = ('', 8000)
# 创建HTTP服务器实例
httpd = HTTPServer(server_address, RouterHandler)
# 打印服务器启动信息
print("路由服务器运行在 http://localhost:8000")
# 启动服务器
httpd.serve_forever()http.server 是学习HTTP协议和服务器工作原理的优秀工具,但在实际项目中通常会被更专业的解决方案替代。