21.22. http.server — HTTP 服务器

源代码: Lib / http / server.py

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

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)

此类通过将服务器地址存储为名为server_nameserver_port的实例变量,在TCPServer类上构建。服务器可由处理程序访问,通常通过处理程序的服务器实例变量。

必须为HTTPServer提供一个RequestHandlerClass实例化,本模块提供三种不同的变体:

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

此类用于处理到达服务器的HTTP请求。它本身不能响应任何实际的HTTP请求;它必须被子类化以处理每个请求方法(例如,GET或POST)。BaseHTTPRequestHandler提供了许多类和实例变量,以及供子类使用的方法。

处理程序将解析请求和头,然后调用特定于请求类型的方法。方法名称由请求构造。例如,对于请求方法SPAM,将调用不带参数的do_SPAM()方法。所有相关信息存储在处理程序的实例变量中。子类不应该覆盖或扩展__init__()方法。

BaseHTTPRequestHandler具有以下实例变量:

client_address

包含引用客户端地址的(主机, 端口)形式的元组。

server

包含服务器实例。

close_connection

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

requestline

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

command

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

path

包含请求路径。

request_version

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

headers

保存由MessageClass类变量指定的类的实例。本实例解析和管理HTTP请求中的头。来自http.clientparse_headers()函数用于解析标头,并且它要求HTTP请求提供有效的 RFC 2822样式标题。

rfile

包含一个输入流,位于可选输入数据的开头。

wfile

包含用于将响应写回客户端的输出流。在写入此流时,必须正确遵守HTTP协议。

BaseHTTPRequestHandler具有以下属性:

server_version

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

sys_version

包含可由version_string方法和server_version类变量使用的Python系统版本。例如,'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类来解析HTTP标头。通常,这不会被覆盖,它默认为http.client.HTTPMessage

responses

此属性包含错误代码整数到包含短和长消息的两元素元组的映射。例如,{code: (shortmessage, longmessage)}短消息通常用作错误响应中的消息键,longmessage作为说明键。它由send_response_only()send_error()方法使用。

A BaseHTTPRequestHandler实例具有以下方法:

handle()

调用handle_one_request()一次(如果启用持久连接,则多次)以处理传入的HTTP请求。你应该永远不需要覆盖它;而是实现适当的do_*()方法。

handle_one_request()

此方法将解析并分派请求到适当的do_*()方法。你应该永远不需要重写它。

handle_expect_100()

当符合HTTP / 1.1标准的服务器接收到期望: 100-继续请求头时,会以/ t4> 继续,然后按200 确定如果服务器不希望客户端继续,则可以覆盖此方法以引发错误。例如,服务器可以选择发送417 期望 失败作为响应标头和t5> False

版本3.2中的新功能。

send_error(code, message=None, explain=None)

向客户端发送并记录完整的错误回复。数字代码指定HTTP错误代码,其中消息是可选的,简短的,可读的错误描述。explain参数可用于提供有关错误的更详细信息;它将使用error_message_format属性格式化,并在一组完整的标题后作为响应正文发出。responses属性保存消息说明的默认值,如果未提供值,将使用该值;对于未知代码,两者的默认值是字符串???如果方法为HEAD或响应代码为以下之一,则正文将为空:1xx204 内容205 重置 内容304 不是 修改

在版本3.4中更改:错误响应包含Content-Length标头。添加了explain参数。

send_response(code, message=None)

向头缓冲区添加响应头,并记录接受的请求。HTTP响应行写入内部缓冲区,随后是服务器日期标题。这两个头的值分别从version_string()date_time_string()方法中选取。如果服务器不打算使用send_header()方法发送任何其他头,则send_response()后应紧跟一个end_headers()

在版本3.3中更改:标题存储到内部缓冲区,end_headers()需要显式调用。

send_header(keyword, value)

将HTTP头添加到内部缓冲区,当调用end_headers()flush_headers()时,将写入输出流。关键字应指定标题关键字,指定其值。注意,在send_header调用完成后,必须调用end_headers()才能完成操作。

在版本3.2中更改:标题存储在内部缓冲区中。

send_response_only(code, message=None)

仅发送响应头,用于在服务器向客户端发送100 继续响应时的目的。标头未缓冲并直接发送输出流。如果未指定消息,则发送与响应代码相对应的HTTP消息。

版本3.2中的新功能。

end_headers()

在标头缓冲区中添加一个空行(表示响应中HTTP头的结尾)并调用flush_headers()

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

flush_headers()

最后发送头到输出流和刷新内部头缓冲区。

版本3.3中的新功能。

log_request(code='-', size='-')

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

log_error(...)

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

log_message(format, ...)

将任意消息记录到sys.stderr这通常被覆盖以创建自定义错误日志记录机制。格式参数是标准的printf样式格式字符串,其中log_message()的附加参数将作为格式化的输入应用。客户端IP地址和当前日期和时间以每个记录的消息为前缀。

version_string()

返回服务器软件的版本字符串。这是server_versionsys_version属性的组合。

date_time_string(timestamp=None)

返回由消息头格式化的timestamp(必须为无或以time.time()返回的格式)给出的日期和时间。如果省略timestamp,则使用当前日期和时间。

结果如'Sun, 06 11月 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.htmlindex.htm的文件(按此顺序)。如果找到,则返回文件的内容;否则通过调用list_directory()方法生成目录列表。此方法使用os.listdir()扫描目录,如果listdir()失败,则会返回404错误响应。

如果请求映射到文件,则会打开它并返回内容。任何打开请求文件的OSError异常映射到404'文件 ,而不是 找到'错误。否则,通过调用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

httpd = socketserver.TCPServer(("", PORT), Handler)

print("serving at port", PORT)
httpd.serve_forever()

还可以使用解释器的-m开关和端口t>直接调用http.server t8>参数。与上一个示例类似,此示例提供相对于当前目录的文件:

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中的完全一样。

注意

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

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

修改do_GET()do_HEAD()函数以运行CGI脚本并提供输出,而不是提供文件,如果请求导向cgi_directories路径。

CGIHTTPRequestHandler定义以下数据成员:

cgi_directories

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

CGIHTTPRequestHandler定义以下方法:

do_POST()

此方法提供'POST'请求类型,仅适用于CGI脚本。错误501,“只能发送到CGI脚本”,当尝试POST到非CGI URL时输出。

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

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

python -m http.server --cgi 8000