http.server
— HTTP 服务器¶
源代码: Lib/http/server.py
此模块定义了用于实现 HTTP 服务器的类。
警告
不建议在生产环境中使用 http.server
。它只实现了 基本的安全性检查。
可用性:不支持 Emscripten,不支持 WASI。
此模块在 WebAssembly 平台 wasm32-emscripten
和 wasm32-wasi
上不可用或无法工作。有关更多信息,请参阅 WebAssembly 平台。
其中一个类,HTTPServer
,是 socketserver.TCPServer
的子类。它在 HTTP 套接字上创建并监听,并将请求分派给处理程序。创建和运行服务器的代码如下所示
def run(server_class=HTTPServer, handler_class=BaseHTTPRequestHandler):
server_address = ('', 8000)
httpd = server_class(server_address, handler_class)
httpd.serve_forever()
- class http.server.HTTPServer(server_address, RequestHandlerClass)¶
此类基于
TCPServer
类构建,将服务器地址存储为名为server_name
和server_port
的实例变量。处理程序可以访问服务器,通常是通过处理程序的server
实例变量。
- class http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)¶
此类与 HTTPServer 相同,但使用线程来处理请求,方法是使用
ThreadingMixIn
。这对于处理网络浏览器预先打开的套接字非常有用,而HTTPServer
会无限期地等待这些套接字。3.7 版新增。
HTTPServer
和 ThreadingHTTPServer
在实例化时必须指定一个 RequestHandlerClass,此模块提供了三种不同的变体
- class http.server.BaseHTTPRequestHandler(request, client_address, server)¶
此类用于处理到达服务器的 HTTP 请求。它本身不能响应任何实际的 HTTP 请求;必须对其进行子类化以处理每个请求方法(例如 GET 或 POST)。
BaseHTTPRequestHandler
提供了许多类和实例变量,以及供子类使用的方法。处理程序将解析请求和标头,然后调用特定于请求类型的方法。方法名称由请求构造。例如,对于请求方法
SPAM
,将调用do_SPAM()
方法,不带任何参数。所有相关信息都存储在处理程序的实例变量中。子类不需要覆盖或扩展__init__()
方法。BaseHTTPRequestHandler
具有以下实例变量- client_address¶
包含一个形式为
(host, port)
的元组,指的是客户端的地址。
- server¶
包含服务器实例。
- close_connection¶
布尔值,应在
handle_one_request()
返回之前设置,指示是否可能收到另一个请求,或者是否应关闭连接。
- requestline¶
包含 HTTP 请求行的字符串表示形式。末尾的 CRLF 被删除。此属性应由
handle_one_request()
设置。如果没有处理有效的请求行,则应将其设置为空字符串。
- command¶
包含命令(请求类型)。例如,
'GET'
。
- request_version¶
包含来自请求的版本字符串。例如,
'HTTP/1.0'
。
- headers¶
保存由
MessageClass
类变量指定的类的实例。此实例解析和管理 HTTP 请求中的标头。来自http.client
的parse_headers()
函数用于解析标头,它要求 HTTP 请求提供有效的 RFC 2822 样式标头。
- rfile¶
一个
io.BufferedIOBase
输入流,准备从可选输入数据的开头读取。
- wfile¶
包含用于将响应写回客户端的输出流。为了实现与 HTTP 客户端的成功互操作,写入此流时必须严格遵守 HTTP 协议。
版本 3.6 中的变化: 这是一个
io.BufferedIOBase
流。
BaseHTTPRequestHandler
具有以下属性- server_version¶
指定服务器软件版本。您可能需要覆盖此项。格式是多个空格分隔的字符串,其中每个字符串的形式为 name[/version]。例如,
'BaseHTTP/0.2'
。
- sys_version¶
包含 Python 系统版本,其格式可由
version_string
方法和server_version
类变量使用。例如,'Python/1.4'
。
- error_message_format¶
指定
send_error()
方法应使用的格式字符串,用于构建对客户端的错误响应。默认情况下,字符串使用responses
中的变量填充,具体取决于传递给send_error()
的状态码。
- error_content_type¶
指定发送到客户端的错误响应的 Content-Type HTTP 标头。默认值为
'text/html'
。
- protocol_version¶
指定服务器符合的 HTTP 版本。它在响应中发送,以使客户端知道服务器对未来请求的通信能力。如果设置为
'HTTP/1.1'
,则服务器将允许 HTTP 持久连接;但是,您的服务器 *必须* 在其对客户端的所有响应中包含准确的Content-Length
标头(使用send_header()
)。为了向后兼容,默认设置为'HTTP/1.0'
。
- MessageClass¶
指定一个类似于
email.message.Message
的类来解析 HTTP 标头。通常,不会覆盖此项,并且默认为http.client.HTTPMessage
。
- responses¶
此属性包含错误代码整数到包含简短消息和长消息的二元组的映射。例如,
{code: (shortmessage, longmessage)}
。*shortmessage* 通常在错误响应中用作 *message* 键,而 *longmessage* 用作 *explain* 键。它由send_response_only()
和send_error()
方法使用。
BaseHTTPRequestHandler
实例具有以下方法- handle()¶
调用一次
handle_one_request()
(或者,如果启用了持久连接,则多次调用)以处理传入的 HTTP 请求。您永远不需要覆盖它;而是实现适当的do_*()
方法。
- handle_one_request()¶
此方法将解析请求并将其分派到相应的
do_*()
方法。您永远不需要覆盖它。
- handle_expect_100()¶
当符合 HTTP/1.1 的服务器收到
Expect: 100-continue
请求标头时,它会使用100 Continue
后跟200 OK
标头进行响应。如果服务器不希望客户端继续,则可以覆盖此方法以引发错误。例如,服务器可以选择发送417 Expectation Failed
作为响应标头并return False
。3.2 版新增。
- send_error(code, message=None, explain=None)¶
向客户端发送并记录完整的错误回复。数字 code 指定 HTTP 错误代码,message 是可选的简短、人类可读的错误描述。explain 参数可用于提供有关错误的更详细信息;它将使用
error_message_format
属性进行格式化,并在完整的标头集之后作为响应正文发出。如果未提供任何值,则responses
属性将保存 message 和 explain 的默认值;对于未知代码,两者的默认值均为字符串???
。如果方法为 HEAD 或响应代码为以下之一,则正文将为空:1xx
、204 No Content
、205 Reset Content
、304 Not Modified
。版本 3.4 中的变化: 错误响应包含 Content-Length 标头。添加了 explain 参数。
- send_response(code, message=None)¶
将响应标头添加到标头缓冲区并记录已接受的请求。HTTP 响应行被写入内部缓冲区,后跟 Server 和 Date 标头。这两个标头的值分别从
version_string()
和date_time_string()
方法中获取。如果服务器不打算使用send_header()
方法发送任何其他标头,则send_response()
之后应调用end_headers()
。版本 3.3 中的变化: 标头存储在内部缓冲区中,并且需要显式调用
end_headers()
。
- send_header(keyword, value)¶
将 HTTP 标头添加到内部缓冲区,当调用
end_headers()
或flush_headers()
时,该缓冲区将被写入输出流。keyword 应指定标头关键字,value 指定其值。请注意,在完成 send_header 调用后,必须调用end_headers()
才能完成操作。版本 3.2 中的变化: 标头存储在内部缓冲区中。
- send_response_only(code, message=None)¶
仅发送响应标头,用于服务器向客户端发送
100 Continue
响应的情况。标头不进行缓冲,直接发送到输出流。如果未指定 message,则发送与响应 code 对应的 HTTP 消息。3.2 版新增。
- end_headers()¶
在标头缓冲区中添加一个空行(表示响应中 HTTP 标头的结尾),并调用
flush_headers()
。版本 3.2 中的变化: 缓冲的标头被写入输出流。
- flush_headers()¶
最后将标头发送到输出流并刷新内部标头缓冲区。
版本 3.3 中的新功能。
- log_request(code='-', size='-')¶
记录已接受(成功)的请求。code 应指定与响应关联的数字 HTTP 代码。如果响应的大小可用,则应将其作为 size 参数传递。
- log_error(...)¶
当请求无法完成时记录错误。默认情况下,它会将消息传递给
log_message()
,因此它采用相同的参数(format 和其他值)。
- log_message(format, ...)¶
将任意消息记录到
sys.stderr
。这通常被覆盖以创建自定义错误记录机制。format 参数是一个标准的 printf 风格的格式字符串,其中log_message()
的其他参数作为输入应用于格式化。客户端 IP 地址和当前日期和时间会添加到每个记录的消息之前。
- version_string()¶
返回服务器软件的版本字符串。这是
server_version
和sys_version
属性的组合。
- date_time_string(timestamp=None)¶
返回由 timestamp(必须为
None
或采用time.time()
返回的格式)给出的日期和时间,格式化为消息标头。如果省略 timestamp,则使用当前日期和时间。结果类似于
'Sun, 06 Nov 1994 08:49:37 GMT'
。
- log_date_time_string()¶
返回当前日期和时间,格式适合记录。
- address_string()¶
返回客户端地址。
3.3 版后已移除: 之前会执行名称查找。为了避免名称解析延迟,现在它总是返回 IP 地址。
- class http.server.SimpleHTTPRequestHandler(request, client_address, server, directory=None)¶
此类提供来自 directory 目录及其子目录中的文件,如果未提供 directory 则提供当前目录中的文件,直接将目录结构映射到 HTTP 请求。
在 3.7 版更改: 添加了 directory 参数。
在 3.9 版更改: directory 参数接受 类路径对象。
许多工作,例如解析请求,都是由基类
BaseHTTPRequestHandler
完成的。 此类实现了do_GET()
和do_HEAD()
函数。以下定义为
SimpleHTTPRequestHandler
的类级属性- server_version¶
这将是
"SimpleHTTP/" + __version__
,其中__version__
在模块级别定义。
- extensions_map¶
一个字典,将后缀映射到 MIME 类型,包含对默认系统映射的自定义覆盖。 映射不区分大小写,因此应仅包含小写的键。
在 3.9 版更改: 此字典不再填充默认系统映射,而仅包含覆盖。
SimpleHTTPRequestHandler
类定义了以下方法- do_GET()¶
通过将请求解释为相对于当前工作目录的路径,将请求映射到本地文件。
如果请求被映射到一个目录,则检查该目录中是否存在名为
index.html
或index.htm
的文件(按此顺序)。 如果找到,则返回文件的内容;否则,通过调用list_directory()
方法生成目录列表。 此方法使用os.listdir()
扫描目录,如果listdir()
失败,则返回404
错误响应。如果请求被映射到一个文件,则打开该文件。 打开请求的文件时出现的任何
OSError
异常都映射到404
,“文件未找到”错误。 如果请求中存在'If-Modified-Since'
标头,并且文件在此时间之后未修改,则发送304
,“未修改”响应。 否则,通过调用guess_type()
方法猜测内容类型,该方法又使用 extensions_map 变量,并返回文件内容。输出一个
'Content-type:'
标头,其中包含猜测的内容类型,后跟一个'Content-Length:'
标头,其中包含文件的大小,以及一个'Last-Modified:'
标头,其中包含文件的修改时间。然后是一个空行,表示标头的结尾,然后输出文件的内容。 如果文件的 MIME 类型以
text/
开头,则以文本模式打开文件;否则使用二进制模式。有关示例用法,请参见 Lib/http/server.py 中
test
函数的实现。在 3.7 版更改: 支持
'If-Modified-Since'
标头。
可以通过以下方式使用 SimpleHTTPRequestHandler
类来创建一个非常基本的 Web 服务器,用于提供相对于当前目录的文件
import http.server
import socketserver
PORT = 8000
Handler = http.server.SimpleHTTPRequestHandler
with socketserver.TCPServer(("", PORT), Handler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()
也可以将 SimpleHTTPRequestHandler
子类化以增强行为,例如通过覆盖类属性 index_pages
来使用不同的索引文件名。
也可以使用解释器的 -m
开关直接调用 http.server
。 与前面的示例类似,这将提供相对于当前目录的文件
python -m http.server
服务器默认侦听端口 8000。 可以通过将所需的端口号作为参数传递来覆盖默认值
python -m http.server 9000
默认情况下,服务器将自身绑定到所有接口。 选项 -b/--bind
指定它应该绑定到的特定地址。 支持 IPv4 和 IPv6 地址。 例如,以下命令使服务器仅绑定到本地主机
python -m http.server --bind 127.0.0.1
在 3.4 版更改: 添加了 --bind
选项。
在 3.8 版更改: 在 --bind
选项中支持 IPv6。
默认情况下,服务器使用当前目录。 选项 -d/--directory
指定它应该为其提供文件的目录。 例如,以下命令使用特定目录
python -m http.server --directory /tmp/
版本 3.7 中的变化: 添加了 --directory
选项。
默认情况下,服务器符合 HTTP/1.0。选项 -p/--protocol
指定服务器符合的 HTTP 版本。例如,以下命令运行一个符合 HTTP/1.1 的服务器
python -m http.server --protocol HTTP/1.1
版本 3.11 中的变化: 添加了 --protocol
选项。
- class http.server.CGIHTTPRequestHandler(request, client_address, server)¶
此类用于从当前目录及其子目录中提供文件或 CGI 脚本的输出。请注意,将 HTTP 层次结构映射到本地目录结构的方式与
SimpleHTTPRequestHandler
中完全相同。注意
CGIHTTPRequestHandler
类运行的 CGI 脚本无法执行重定向(HTTP 代码 302),因为代码 200(脚本输出跟随)是在执行 CGI 脚本之前发送的。这会抢占状态代码。但是,如果该类猜测某个文件是 CGI 脚本,它将运行该脚本,而不是将其作为文件提供。只使用基于目录的 CGI - 另一种常见的服务器配置是将特殊扩展名视为表示 CGI 脚本。
修改了
do_GET()
和do_HEAD()
函数,以便在请求指向cgi_directories
路径下的某个位置时运行 CGI 脚本并提供输出,而不是提供文件。CGIHTTPRequestHandler
定义了以下数据成员- cgi_directories¶
默认为
['/cgi-bin', '/htbin']
,描述了要视为包含 CGI 脚本的目录。
CGIHTTPRequestHandler
定义了以下方法- do_POST()¶
此方法用于处理
'POST'
请求类型,该类型仅允许用于 CGI 脚本。尝试向非 CGI url 发送 POST 请求时,会输出错误 501,“只能向 CGI 脚本发送 POST 请求”。
请注意,出于安全原因,CGI 脚本将以用户 nobody 的 UID 运行。CGI 脚本的问题将转换为错误 403。
可以通过传递 --cgi
选项在命令行中启用 CGIHTTPRequestHandler
python -m http.server --cgi
警告
CGIHTTPRequestHandler
和 --cgi
命令行选项不适用于不受信任的客户端,并且可能容易受到攻击。始终在安全的环境中使用。
安全注意事项¶
SimpleHTTPRequestHandler
在处理请求时会跟随符号链接,这使得指定目录之外的文件也可能被提供。
早期版本的 Python 不会清除从 python -m http.server
或默认的 BaseHTTPRequestHandler
.log_message
实现发送到 stderr 的日志消息中的控制字符。这可能会允许连接到你的服务器的远程客户端向你的终端发送恶意控制代码。
版本 3.12 中的变化: stderr 日志中的控制字符已被清除。