21.22. http.server — HTTP 服务器 — Python 文档
21.22. http.server — HTTP 服务器
源代码: :source:`Lib/http/server.py`
该模块定义了用于实现 HTTP 服务器(Web 服务器)的类。
一类,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
实例变量。
HTTPServer 在实例化时必须被赋予一个 RequestHandlerClass,该模块提供了三种不同的变体:
- class http.server.BaseHTTPRequestHandler(request, client_address, server)
该类用于处理到达服务器的 HTTP 请求。 它本身无法响应任何实际的 HTTP 请求; 它必须被子类化以处理每个请求方法(例如 获取或发布)。 BaseHTTPRequestHandler 提供了许多类和实例变量,以及供子类使用的方法。
处理程序将解析请求和标头,然后调用特定于请求类型的方法。 方法名称是根据请求构造的。 例如,对于请求方法
SPAM
,将不带参数调用do_SPAM()
方法。 所有相关信息都存储在处理程序的实例变量中。 子类不需要覆盖或扩展__init__()
方法。BaseHTTPRequestHandler 有以下实例变量:
- client_address
包含一个
(host, port)
形式的元组,引用客户端的地址。
- server
包含服务器实例。
- close_connection
应在 handle_one_request() 返回之前设置的布尔值,指示是否可能需要另一个请求,或者是否应关闭连接。
- requestline
包含 HTTP 请求行的字符串表示形式。 终止 CRLF 被剥离。 此属性应由 handle_one_request() 设置。 如果没有处理有效的请求行,则应将其设置为空字符串。
- command
包含命令(请求类型)。 例如,
'GET'
。
- path
包含请求路径。
- 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() 方法应使用的格式字符串,以构建对客户端的错误响应。 默认情况下,根据传递给 send_error() 的状态代码,使用来自 responses 的变量填充字符串。
- 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-like 类来解析 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)
此类提供来自当前目录及以下目录的文件,直接将目录结构映射到 HTTP 请求。
很多工作,比如解析请求,都是由基类BaseHTTPRequestHandler来完成的。 这个类实现了 do_GET() 和 do_HEAD() 函数。
以下定义为 SimpleHTTPRequestHandler 的类级属性:
- server_version
这将是
"SimpleHTTP/" + __version__
,其中__version__
在模块级别定义。
- extensions_map
字典映射后缀到 MIME 类型。 默认值由空字符串表示,被认为是
application/octet-stream
。 该映射不区分大小写,因此应仅包含小写的键。
SimpleHTTPRequestHandler 类定义了以下方法:
- do_HEAD()
此方法服务于
'HEAD'
请求类型:它发送它会为等效的GET
请求发送的标头。 有关可能的标头的更完整说明,请参阅 do_GET() 方法。
- do_GET()
通过将请求解释为相对于当前工作目录的路径,将请求映射到本地文件。
如果请求已映射到目录,则会检查目录中是否存在名为
index.html
或index.htm
(按此顺序)的文件。 如果找到,则返回文件的内容; 否则将通过调用list_directory()
方法生成目录列表。 此方法使用 os.listdir() 扫描目录,如果 listdir() 失败,则返回404
错误响应。如果请求被映射到一个文件,它会被打开并返回内容。 打开请求文件时的任何 OSError 异常都映射到
404
、'File not found'
错误。 否则,通过调用guess_type()
方法猜测内容类型,该方法又使用 extensions_map 变量。输出带有猜测内容类型的
'Content-type:'
标头,然后是带有文件大小的'Content-Length:'
标头和带有文件修改时间的'Last-Modified:'
标头。然后跟随一个表示标题结束的空行,然后输出文件的内容。 如果文件的 MIME 类型以
text/
开头,则文件以文本模式打开; 否则使用二进制模式。例如用法,参见http.server模块中test()函数调用的实现。
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()
http.server 也可以使用解释器的 -m 开关和 port number
参数直接调用。 与前面的示例类似,这提供了相对于当前目录的文件:
python -m http.server 8000
默认情况下,服务器将自身绑定到所有接口。 选项 -b/--bind
指定它应该绑定到的特定地址。 例如,以下命令会导致服务器仅绑定到 localhost:
python -m http.server 8000 --bind 127.0.0.1
3.4 版新功能:引入了 --bind
参数。
- class http.server.CGIHTTPRequestHandler(request, client_address, server)
此类用于提供当前目录及以下目录中的文件或 CGI 脚本的输出。 请注意,将 HTTP 层次结构映射到本地目录结构与 SimpleHTTPRequestHandler 中的完全相同。
笔记
CGIHTTPRequestHandler 类运行的 CGI 脚本无法执行重定向(HTTP 代码 302),因为代码 200(脚本输出如下)是在执行 CGI 脚本之前发送的。 这会抢占状态代码。
但是,如果该类猜测它是 CGI 脚本,则该类将运行 CGI 脚本,而不是将其作为文件提供。 仅使用基于目录的 CGI — 另一个常见的服务器配置是将特殊扩展视为表示 CGI 脚本。
do_GET()
和do_HEAD()
函数被修改为运行 CGI 脚本并提供输出,而不是提供文件,如果请求指向cgi_directories
路径下方的某处。CGIHTTPRequestHandler 定义了以下数据成员:
- cgi_directories
默认为
['/cgi-bin', '/htbin']
并描述要视为包含 CGI 脚本的目录。
CGIHTTPRequestHandler 定义了以下方法:
- do_POST()
此方法服务于
'POST'
请求类型,仅允许用于 CGI 脚本。 尝试 POST 到非 CGI url 时会输出错误 501,“只能 POST 到 CGI 脚本”。
请注意,出于安全原因,CGI 脚本将使用用户 nobody 的 UID 运行。 CGI 脚本的问题将转换为错误 403。
CGIHTTPRequestHandler 可以通过传递 --cgi
选项在命令行中启用:
python -m http.server --cgi 8000