http.server — HTTP 服务器

源代码: Lib/http/server.py


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

Warning

不建议将http.server用于生产。它仅实现基本的安全检查。

一类HTTPServersocketserver.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 *)
    • 此类pass将服务器地址存储为名为server_nameserver_port的实例变量来构建TCPServer类。处理程序通常可以pass处理程序的server实例变量来访问服务器。
    • class * http.server. ThreadingHTTPServer(* server_address RequestHandlerClass *)
    • 此类与 HTTPServer 相同,但是使用线程passThreadingMixIn处理请求。这对于处理预打开套接字的 Web 浏览器很有用,HTTPServer将在该套接字上无限期 await。

3.7 版中的新Function。

必须在实例化时为HTTPServerThreadingHTTPServer提供* RequestHandlerClass *,该模块提供了三种不同的变体:

    • class * http.server. BaseHTTPRequestHandler(* request client_address server *)
    • 此类用于处理到达服务器的 HTTP 请求。就其本身而言,它无法响应任何实际的 HTTP 请求。必须将其子类化以处理每种请求方法(例如 GET 或 POST)。 BaseHTTPRequestHandler提供了许多类和实例变量,以及供子类使用的方法。

处理程序将解析请求和 Headers,然后调用特定于请求类型的方法。方法名称是根据请求构造的。例如,对于请求方法SPAM,将不带任何参数调用do_SPAM()方法。所有相关信息都存储在处理程序的实例变量中。子类不需要重写或扩展init()方法。

BaseHTTPRequestHandler具有以下实例变量:

  • client_address

    • 包含表示 Client 地址的(host, port)形式的 Tuples。
  • server

    • 包含服务器实例。
  • close_connection

    • 应该在handle_one_request()返回之前设置的布尔值,指示是否可能期望另一个请求,或者是否应该关闭连接。
  • requestline

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

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

    • 包含请求路径。
  • request_version

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

    • 包含MessageClass class 变量指定的类的实例。该实例解析并 ManagementHTTP 请求中的 Headers。 http.client中的parse_headers()函数用于解析 Headers,它要求 HTTP 请求提供有效的 RFC 2822样式 Headers。
  • rfile

    • io.BufferedIOBaseImporting 流,准备从可选 Importing 数据的开头读取。
  • wfile

    • 包含用于将响应写回到 Client 端的输出流。写入此流时,必须使用正确的 HTTP 协议,以实现与 HTTPClient 端的成功互操作。

在版本 3.6 中更改:这是io.BufferedIOBase流。

BaseHTTPRequestHandler具有以下属性:

  • server_version

    • 指定服务器软件版本。您可能要覆盖它。格式是多个用空格分隔的字符串,其中每个字符串的格式均为名称[/ version]。例如'BaseHTTP/0.2'
  • sys_version

  • error_message_format

    • 指定send_error()方法应使用的格式字符串,以构建对 Client 端的错误响应。默认情况下,根据传递给send_error()的状态代码,使用responses中的变量填充字符串。
  • error_content_type

    • 指定发送到 Client 端的错误响应的 Content-Type HTTPHeaders。默认值为'text/html'
  • protocol_version

    • 这指定了响应中使用的 HTTP 协议版本。如果设置为'HTTP/1.1',则服务器将允许 HTTP 持久连接;但是,您的服务器在所有对 Client 端的响应中都必须*包含一个准确的Content-LengthHeaders(使用send_header())。为了向后兼容,该设置默认为'HTTP/1.0'
  • MessageClass

    • 指定一个类似于email.message.Message的类来解析 HTTPHeaders。通常,不会覆盖它,并且默认为http.client.HTTPMessage
  • responses

    • 此属性包含错误代码整数到包含短消息和长消息的两个元素的 Tuples 的 Map。例如{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请求 Headers 时,它将以100 Continue后跟200 OKHeaders 进行响应。如果服务器不希望 Client 端 continue,则可以重写此方法以引发错误。例如服务器可以选择发送417 Expectation Failed作为响应头和return False

3.2 版中的新Function。

  • send_error(* code message = None explain = None *)
    • 发送并记录完整的错误回复给 Client 端。数字* code 指定 HTTP 错误代码,而 message *作为可选的,简短的,人类可读的错误描述。 * explain 参数可用于提供有关错误的更多详细信息;它将使用error_message_format属性进行格式化,并在完整的标题集之后作为响应主体发出。 responses属性保存 message explain *的默认值,如果不提供任何值,将使用这些默认值;对于未知代码,两者的默认值都是字符串???。如果方法为 HEAD 或响应代码为以下值之一,则主体将为空:1xx204 No Content205 Reset Content304 Not Modified

在版本 3.4 中更改:错误响应包括 Content-LengthHeaders。添加了* explain *参数。

  • send_response(* code message = None *)
    • 将响应 Headers 添加到 Headers 缓冲区,并记录接受的请求。 HTTP 响应行被写入内部缓冲区,后跟* Server Date *Headers。这两个 Headers 的值分别从version_string()date_time_string()方法中选取。如果服务器不打算使用send_header()方法发送任何其他 Headers,则应在send_response()之后跟一个end_headers()调用。

在版本 3.3 中进行了更改:Headers 存储在内部缓冲区中,并且需要明确调用end_headers()

  • send_header(关键字)
    • 将 HTTPHeaders 添加到内部缓冲区中,当调用end_headers()flush_headers()时,该缓冲区将被写入输出流。 * keyword 应该指定 Headers 关键字, value *指定其值。请注意,在完成 send_header 调用之后,必须调用end_headers()才能完成操作。

在版本 3.2 中进行了更改:Headers 存储在内部缓冲区中。

  • send_response_only(* code message = None *)
    • 仅发送响应头,用于服务器将100 Continue响应发送到 Client 端时使用。Headers 未缓冲并直接发送到输出流。如果未指定* message ,则会发送与响应 code *相对应的 HTTP 消息。

3.2 版中的新Function。

  • end_headers ( )
    • 在 Headers 缓冲区中添加一个空行(指示响应中 HTTPHeaders 的末尾)并调用flush_headers()

在版本 3.2 中更改:将缓冲的 Headers 写入输出流。

  • flush_headers ( )
    • 最后,将 Headers 发送到输出流,并刷新内部 Headers 缓冲区。

版本 3.3 中的新Function。

  • log_request(* code ='-' size ='-'*)

    • 记录接受(成功)的请求。 * code 应该指定与响应关联的数字 HTTP 代码。如果响应的大小可用,则应将其作为 size *参数传递。
  • log_error ( ... )

    • 无法满足请求时记录错误。默认情况下,它将消息传递给log_message(),因此它采用相同的参数(* format *和其他值)。
  • log_message(* format ... *)

    • 将任意消息记录到sys.stderr。通常将其覆盖以创建自定义错误日志记录机制。 * format *参数是标准的 printf 样式格式字符串,其中log_message()的其他参数用作格式的 Importing。Client 端 ip 地址以及当前日期和时间是每个记录的消息的前缀。
  • version_string ( )

  • date_time_string(* timestamp = None *)

    • 返回* timestamp (必须为Nonetime.time()返回的格式)给定的日期和时间,格式为消息头。如果Ellipsis timestamp *,则使用当前日期和时间。

结果看起来像'Sun, 06 Nov 1994 08:49:37 GMT'

  • log_date_time_string ( )

    • 返回当前日期和时间,格式设置为日志记录。
  • address_string ( )

    • 返回 Client 地址。

在版本 3.3 中进行了更改:以前执行过名称查找。为了避免名称解析延迟,它现在始终返回 IP 地址。

    • class * http.server. SimpleHTTPRequestHandler(* request client_address server directory = None *)
    • 此类提供当前目录及以下目录中的文件,直接将目录结构 Map 到 HTTP 请求。

Base ClassBaseHTTPRequestHandler完成了很多工作,例如解析请求。此类实现do_GET()do_HEAD()函数。

以下定义为SimpleHTTPRequestHandler的类级属性:

  • server_version

    • 这将是"SimpleHTTP/" + __version__,其中__version__是在模块级别定义的。
  • extensions_map

    • 字典 Map 后缀为 MIME 类型。默认值由空字符串表示,并被视为application/octet-stream。Map 不区分大小写,因此应仅包含小写字母的键。
  • directory

    • 如果未指定,则要服务的目录是当前工作目录。

SimpleHTTPRequestHandler类定义以下方法:

  • do_HEAD ( )

    • 此方法提供'HEAD'请求类型:它发送将为等效的GET请求发送的 Headers。有关可能的标题的更完整说明,请参见do_GET()方法。
  • do_GET ( )

    • pass将请求解释为相对于当前工作目录的路径,将请求 Map 到本地文件。

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

如果请求已 Map 到文件,则将其打开。打开请求的文件中的任何OSError异常都将 Map 到404'File not found'错误。如果请求中有一个'If-Modified-Since'Headers,并且在此之后未修改文件,则发送304'Not Modified'响应。否则,pass调用guess_type()方法来猜测 Content Type,该方法又使用* extensions_map *变量,并返回文件内容。

输出具有猜想的 Content Type 的'Content-type:'Headers,然后输出具有文件大小的'Content-Length:'Headers 和具有文件修改时间的'Last-Modified:'Headers。

然后跟随一个空白行,表示标题的末尾,然后输出文件的内容。如果文件的 MIME 类型以text/开头,则以文本模式打开文件;否则使用二进制模式。

有关用法示例,请参见http.server模块中test()函数调用的实现。

在版本 3.7 中更改:支持'If-Modified-Since'Headers。

可以按以下方式使用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()

也可以使用带port number参数的解释器的-m开关直接调用http.server。与前面的示例类似,此命令提供相对于当前目录的文件:

python -m http.server 8000

默认情况下,服务器将自身绑定到所有接口。选项-b/--bind指定应绑定的特定地址。 IPv4 和 IPv6 地址均受支持。例如,以下命令导致服务器仅绑定到 localhost:

python -m http.server 8000 --bind 127.0.0.1

3.4 版中的新Function:引入了--bind参数。

3.8 版中的新Function:--bind参数得到增强,以支持 IPv6

默认情况下,服务器使用当前目录。选项-d/--directory指定应将文件提供到的目录。例如,以下命令使用特定目录:

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

3.7 版中的新Function:--directory指定备用目录

    • class * http.server. CGIHTTPRequestHandler(* request client_address server *)
    • 此类用于从当前目录和下方提供文件或 CGI 脚本的输出。请注意,将 HTTP 层次结构 Map 到本地目录结构与SimpleHTTPRequestHandler完全相同。

Note

CGIHTTPRequestHandler类运行的 CGI 脚本无法执行重定向(HTTP 代码 302),因为在执行 CGI 脚本之前已发送了代码 200(脚本输出如下)。这会抢占状态码。

但是,如果类认为它是 CGI 脚本,则将运行 CGI 脚本,而不是将其用作文件。仅使用基于目录的 CGI-其他常见的服务器配置是将特殊扩展视为表示 CGI 脚本。

修改了do_GET()do_HEAD()函数,以运行 CGI 脚本,并在请求指向cgi_directories路径以下的位置时,而不是为文件提供输出。

CGIHTTPRequestHandler定义以下数据成员:

  • cgi_directories
    • 默认为['/cgi-bin', '/htbin'],并描述要包含 CGI 脚本的目录。

CGIHTTPRequestHandler定义以下方法:

  • do_POST ( )
    • 此方法提供'POST'请求类型,仅 CGI 脚本允许。try POST 到非 CGI URL 时,输出错误 501“只能 POST 到 CGI 脚本”。

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

可以pass传递--cgi选项在命令行中启用CGIHTTPRequestHandler

python -m http.server --cgi 8000