http.server — HTTP 服务器

源代码: Lib/http/server.py


此模块定义了用于实现 HTTP 服务器的类。

警告

http.server 不推荐用于生产环境。它只实现了基本的安全检查

可用性:非 WASI。

此模块在 WebAssembly 上不起作用或不可用。有关更多信息,请参阅 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_nameserver_port 的实例变量。服务器可通过处理器访问,通常通过处理器的 server 实例变量。

class http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)

此类与 HTTPServer 相同,但使用 ThreadingMixIn 使用线程处理请求。这对于处理网络浏览器预打开套接字非常有用,否则 HTTPServer 将无限期等待。

在 3.7 版本加入。

class http.server.HTTPSServer(server_address, RequestHandlerClass, bind_and_activate=True, *, certfile, keyfile=None, password=None, alpn_protocols=None)

HTTPServer 的子类,使用 ssl 模块封装套接字。如果 ssl 模块不可用,则实例化 HTTPSServer 对象将导致 RuntimeError 失败。

certfile 参数是 SSL 证书链文件的路径,keyfile 是包含私钥的文件的路径。

可以为受 PKCS#8 保护和封装的文件指定 password,但请注意,这可能会以明文形式公开硬编码密码。

参见

有关 certfilekeyfilepassword 接受值的更多信息,请参阅 ssl.SSLContext.load_cert_chain()

指定时,alpn_protocols 参数必须是字符串序列,指定服务器支持的“应用层协议协商”(ALPN) 协议。ALPN 允许服务器和客户端在 TLS 握手期间协商应用协议。

默认情况下,它设置为 ["http/1.1"],这意味着服务器支持 HTTP/1.1。

在 3.14 版本加入。

class http.server.ThreadingHTTPSServer(server_address, RequestHandlerClass, bind_and_activate=True, *, certfile, keyfile=None, password=None, alpn_protocols=None)

此类与 HTTPSServer 相同,但通过继承 ThreadingMixIn 使用线程处理请求。这类似于 ThreadingHTTPServer,只是使用 HTTPSServer

在 3.14 版本加入。

HTTPServerThreadingHTTPServerHTTPSServerThreadingHTTPSServer 在实例化时必须给定一个 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() 返回之前应设置为 True 的布尔值,指示是否可以预期另一个请求,或者是否应关闭连接。

requestline

包含 HTTP 请求行的字符串表示形式。终止的 CRLF 被剥离。此属性应由 handle_one_request() 设置。如果未处理任何有效请求行,则应将其设置为空字符串。

command

包含命令(请求类型)。例如,'GET'

path

包含请求路径。如果 URL 的查询组件存在,则 path 包含查询。使用 RFC 3986 的术语,此处的 path 包含 hier-partquery

request_version

包含请求中的版本字符串。例如,'HTTP/1.0'

headers

保存由 MessageClass 类变量指定的类的实例。此实例解析并管理 HTTP 请求中的标头。parse_headers() 函数来自 http.client 用于解析标头,并且它要求 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 属性保存 messageexplain 的默认值,如果未提供值,则将使用这些默认值;对于未知代码,两者的默认值都是字符串 ???。如果方法是 HEAD 或响应代码是以下之一:1xx204 No Content205 Reset Content304 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_versionsys_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_HEAD()

此方法处理 'HEAD' 请求类型:它发送与等效 GET 请求相同的标头。有关可能标头的更完整说明,请参见 do_GET() 方法。

do_GET()

通过将请求解释为相对于当前工作目录的路径,将请求映射到本地文件。

如果请求映射到目录,则会在该目录中检查名为 index.htmlindex.htm 的文件(按此顺序)。如果找到,则返回文件内容;否则通过调用 list_directory() 方法生成目录列表。此方法使用 os.listdir() 扫描目录,如果 listdir() 失败,则返回 404 错误响应。

如果请求映射到文件,则打开该文件。打开请求文件时发生的任何 OSError 异常都将映射到 404'File not found' 错误。如果请求中有 'If-Modified-Since' 标头,并且文件在此时间之后未修改,则发送 304'Not Modified' 响应。否则,通过调用 guess_type() 方法猜测内容类型,该方法反过来使用 extensions_map 变量,然后返回文件内容。

输出一个带有猜测内容类型的 'Content-type:' 标头,后跟一个带有文件大小的 'Content-Length:' 标头,以及一个带有文件修改时间的 'Last-Modified:' 标头。

然后是一个空行,表示标头的结束,然后输出文件内容。

有关用法示例,请参见 Lib/http/server.pytest 函数的实现。

3.7 版中已更改: 支持 'If-Modified-Since' 标头。

SimpleHTTPRequestHandler 类可以按以下方式使用,以创建一个非常基本的网络服务器,提供相对于当前目录的文件:

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 来使用不同的索引文件名。

class http.server.CGIHTTPRequestHandler(request, client_address, server)

此类用于从当前目录及以下提供文件或 CGI 脚本的输出。请注意,HTTP 分层结构到本地目录结构的映射与 SimpleHTTPRequestHandler 中完全相同。

备注

CGIHTTPRequestHandler 类运行的 CGI 脚本不能执行重定向 (HTTP 代码 302),因为在 CGI 脚本执行之前发送了代码 200 (脚本输出随后)。这抢占了状态码。

但是,如果它猜测是 CGI 脚本,该类将运行 CGI 脚本,而不是将其作为文件提供。仅使用基于目录的 CGI —— 另一个常见的服务器配置是将特殊扩展名视为表示 CGI 脚本。

如果请求导致 cgi_directories 路径下的某个位置,则 do_GET()do_HEAD() 函数将修改为运行 CGI 脚本并提供输出,而不是提供文件。

CGIHTTPRequestHandler 定义了以下数据成员:

cgi_directories

此值默认为 ['/cgi-bin', '/htbin'],并描述了应被视为包含 CGI 脚本的目录。

CGIHTTPRequestHandler 定义了以下方法:

do_POST()

此方法用于处理 'POST' 请求类型,仅允许 CGI 脚本使用。当尝试向非 CGI URL 发送 POST 请求时,会输出错误 501,“Can only POST to CGI scripts”。

请注意,出于安全原因,CGI 脚本将以用户 nobody 的 UID 运行。CGI 脚本的问题将转换为错误 403。

自 3.13 版弃用,将在 3.15 版中移除: CGIHTTPRequestHandler 将在 3.15 版中移除。CGI 在十多年来一直不被认为是好的做法。这段代码已经有一段时间无人维护,并且实际使用量很少。保留它可能会导致进一步的安全考虑

命令行界面

http.server 也可以使用解释器的 -m 开关直接调用。以下示例说明了如何提供相对于当前目录的文件:

python -m http.server [OPTIONS] [port]

接受以下选项

port

服务器默认监听 8000 端口。可以通过将所需的端口号作为参数传递来覆盖默认值:

python -m http.server 9000
-b, --bind <address>

指定它应绑定的特定地址。支持 IPv4 和 IPv6 地址。默认情况下,服务器绑定到所有接口。例如,以下命令使服务器仅绑定到 localhost:

python -m http.server --bind 127.0.0.1

在 3.4 版本加入。

3.8 版中已更改: --bind 选项支持 IPv6。

-d, --directory <dir>

指定服务器应从中提供文件的目录。默认情况下,服务器使用当前目录。例如,以下命令使用特定目录:

python -m http.server --directory /tmp/

在 3.7 版本加入。

-p, --protocol <version>

指定服务器符合的 HTTP 版本。默认情况下,服务器符合 HTTP/1.0。例如,以下命令运行一个符合 HTTP/1.1 的服务器:

python -m http.server --protocol HTTP/1.1

在 3.11 版本中新增。

--cgi

CGIHTTPRequestHandler 可以在命令行中通过传递 --cgi 选项来启用:

python -m http.server --cgi

自 3.13 版弃用,将在 3.15 版中移除: http.server 命令行 --cgi 支持正在被移除,因为 CGIHTTPRequestHandler 正在被移除。

警告

CGIHTTPRequestHandler--cgi 命令行选项不适用于不受信任的客户端,并且可能容易受到攻击。请务必在安全环境中使用。

--tls-cert

为 HTTPS 连接指定 TLS 证书链。

python -m http.server --tls-cert fullchain.pem

在 3.14 版本加入。

--tls-key

为 HTTPS 连接指定私钥文件。

此选项需要指定 --tls-cert

在 3.14 版本加入。

--tls-password-file

为受密码保护的私钥指定密码文件。

python -m http.server \
       --tls-cert cert.pem \
       --tls-key key.pem \
       --tls-password-file password.txt

此选项需要指定 –tls-cert`

在 3.14 版本加入。

安全考虑

SimpleHTTPRequestHandler 在处理请求时会遵循符号链接,这使得指定目录之外的文件也可以被提供。

早期版本的 Python 不会从 python -m http.server 或默认的 BaseHTTPRequestHandler .log_message 实现发送到 stderr 的日志消息中清除控制字符。这可能允许连接到您的服务器的远程客户端向您的终端发送恶意的控制代码。

3.12 版中已更改: stderr 日志中的控制字符已被清除。