1: 运行一个简单的 HTTP 服务器
python -m http.server 9000
运行此命令将在端口 9000 上提供当前目录中的文件。
如果未提供端口号作为参数,则服务器将在默认端口 8000 上运行。
-m 标志会在 sys.path 中查找对应的 .py 文件并将其作为模块运行。
如果你只想在本地主机上提供服务,你需要编写一个自定义的 Python 程序,如下所示:
import http.server
import socketserver
import sys
# 设置请求处理类
HandlerClass = http.server.SimpleHTTPRequestHandler
# 设置服务器类
ServerClass = socketserver.TCPServer
# 设置协议版本
Protocol = "HTTP/1.0"
# 获取端口号
if len(sys.argv) > 1:
port = int(sys.argv[1])
else:
port = 8000
# 设置服务器地址
server_address = ('127.0.0.1', port)
# 设置协议版本
HandlerClass.protocol_version = Protocol
# 创建 HTTP 服务器
httpd = ServerClass(server_address, HandlerClass)
# 获取服务器绑定的地址和端口
sa = httpd.server_address
# 打印服务信息
print(f"Serving HTTP on {sa[0]} port {sa[1]}...")
# 开始服务
httpd.serve_forever()
2: 提供文件服务
假设你有以下文件目录:
你可以按照以下方式设置一个 Web 服务器来提供这些文件:
import http.server
import socketserver
PORT = 8000
handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", PORT), handler)
print("serving at port", PORT)
httpd.serve_forever()
SocketServer 模块提供了设置网络服务器的类和功能。
SocketServer 的 TCPServer 类使用 TCP 协议设置服务器。构造函数接受一个表示服务器地址的元组(即 IP 地址和端口)以及处理服务器请求的类。
SimpleHTTPServer 模块的 SimpleHTTPRequestHandler 类允许提供当前目录中的文件。
将脚本保存在同一个目录中并运行它。
运行 HTTP 服务器:
Python 3.x Version ≥ 3.0
python -m http.server 8000
'-m' 标志会在 sys.path 中查找对应的 .py 文件并将其作为模块运行。
在浏览器中打开 localhost:8000,它将显示以下内容:
3: 使用 BaseHTTPRequestHandler基本处理 GET、POST 和 PUT
from http.server import BaseHTTPRequestHandler, HTTPServer
class HandleRequests(BaseHTTPRequestHandler):
def _set_headers(self):
"""设置响应头"""
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
"""处理 GET 请求"""
self._set_headers()
self.wfile.write(b"received get request")
def do_POST(self):
"""处理 POST 请求"""
self._set_headers()
content_len = int(self.headers.get('Content-Length', 0)) # 修正获取 Content-Length 的方法
post_body = self.rfile.read(content_len) # 读取 POST 请求体
self.wfile.write(f"received post request:
{post_body.decode('utf-8')}".encode('utf-8')) # 写入响应内容
def do_PUT(self):
"""处理 PUT 请求(复用 POST 的逻辑)"""
self.do_POST()
# 设置主机和端口
host = ''
port = 8000 # 注意:在非 root 用户下运行时,通常需要使用大于 1024 的端口号,否则会报权限错误
# 创建并启动 HTTP 服务器
HTTPServer((host, port), HandleRequests).serve_forever()
使用 curl 的示例输出:
$ curl http://localhost:8000
received get request%
$ curl -X POST http://localhost:8000
received post request:
%
$ curl -X PUT http://localhost:8000
received post request:
%
$ echo 'hello world' | curl --data-binary @- http://localhost:8000
received post request:
hello world
4: SimpleHTTPServer的编程 API
当我们执行 python -m SimpleHTTPServer 9000 时会发生什么?
要回答这个问题,我们需要了解 SimpleHTTPServer 的构造。
https://hg.python.org/cpython/file/2.7/Lib/SimpleHTTPServer.py 和
https://hg.python.org/cpython/file/2.7/Lib/BaseHTTPServer.py
首先,Python 使用 9000 作为参数调用 SimpleHTTPServer 模块。现在观察 SimpleHTTPServer 的代码:
def test(HandlerClass = SimpleHTTPRequestHandler,
ServerClass = BaseHTTPServer.HTTPServer):
BaseHTTPServer.test(HandlerClass, ServerClass)
if __name__ == '__main__':
test()
test 函数被调用,随后调用请求处理器和服务器类。现在调用 BaseHTTPServer.test:
def test(HandlerClass = BaseHTTPRequestHandler,
ServerClass = HTTPServer, protocol="HTTP/1.0"):
"""Test the HTTP request handler class.
This runs an HTTP server on port 8000 (or the first command line
argument).
"""
if sys.argv[1:]:
port = int(sys.argv[1])
else:
port = 8000
server_address = ('', port)
HandlerClass.protocol_version = protocol
httpd = ServerClass(server_address, HandlerClass)
sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
httpd.serve_forever()
因此,这里解析了用户作为参数传递的端口号,并将其绑定到主机地址。然后执行了给定端口和协议的基本套接字编程步骤。最后启动了套接字服务器。
这是从 SocketServer 类到其他类的继承概述:
+------------+
| BaseServer |
+------------+
|v
+-----------+ +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|v
+-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
以下链接可用于查找更多信息:
https://hg.python.org/cpython/file/2.7/Lib/BaseHTTPServer.py
https://hg.python.org/cpython/file/2.7/Lib/SocketServer.py