简介
源代码: Lib/http/server.py
这个模块定义了实现HTTP服务器(Web服务器)的类。
**警告:**http。不建议在生产环境中使用服务器。它只实现基本的安全检查。
类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)
该类通过将服务器地址存储为实例变量server_name和server_port,构建在TCPServer类的基础上。处理程序可以访问服务器,通常通过处理程序的服务器实例变量。
class http.server.ThreadingHTTPServer(server_address, RequestHandlerClass)
该类与HTTPServer相同,但是使用线程通过ThreadingMixIn处理请求。这对于处理web浏览器预打开套接字(HTTPServer将无限期地等待)非常有用。
必须在实例化时给HTTPServer和ThreadingHTTPServer一个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
包含命令(请求类型)。例如,“得到”。
path
包含请求路径。
request_version
包含请求的版本字符串。例如,“HTTP / 1.0”。
headers
保存MessageClass类变量指定的类的实例。此实例解析和管理HTTP请求中的头。http中的parse_headers()函数。client用于解析报头,它要求HTTP请求提供一个有效的RFC 2822样式报头。
rfile
一个io。缓冲二段输入流,准备从可选的输入数据开始读取。
wfile
包含用于将响应写回客户机的输出流。在写入此流时,必须正确遵守HTTP协议,以实现与HTTP客户机的成功互操作。
BaseHTTPRequestHandler的属性
server_version
指定服务器软件版本。您可能想要覆盖它。格式是多个空格分隔的字符串,其中每个字符串都是表单名称[/version]。例如,“BaseHTTP / 0.2”。
sys_version
包含Python系统版本,其形式可由version_string方法和server_version类变量使用。例如,Python / 1.4。
error_message_format
指定send_error()方法应该使用的格式字符串,用于构建对客户机的错误响应。默认情况下,根据传递给send_error()的状态代码,用响应中的变量填充字符串。
error_content_type
指定发送到客户机的错误响应的内容类型HTTP头。默认值是’text/html’。
protocol_version
这指定了响应中使用的HTTP协议版本。如果设置为“HTTP/1.1”,服务器将允许HTTP持久连接;但是,您的服务器必须在它对客户机的所有响应中包含一个精确的内容长度报头(使用send_header())。为了向后兼容,默认设置为“HTTP/1.0”。
MessageClass
指定一个email.message。类来解析HTTP头文件。通常,这不会被覆盖,并且默认为http.client.HTTPMessage。
responses
此属性包含错误代码整数到包含短消息和长消息的二元元组的映射。例如,{code:(shortmessage, longmessage)}。短消息通常用作错误响应中的消息键,长消息用作解释键。它由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期望失败作为响应头,返回False。
send_error(code, message=None, explain=None)
向客户端发送并记录完整的错误回复。数字代码指定HTTP错误代码,消息作为可选的、简短的、人类可读的错误描述。explain参数可以用来提供关于错误的更详细的信息;它将使用error_message_format属性进行格式化,并在一组完整的头部之后作为响应主体发出。响应属性保存消息的默认值,如果没有提供值,则使用explain;对于未知代码,两者的默认值都是字符串??。如果方法是HEAD或响应代码是以下内容之一,则主体将为空:1xx、204 No Content、205 Reset Content、304 Not Modified。
send_response(code, message=None)
将响应标头添加到标头缓冲区并记录接受的请求。HTTP响应行被写入内部缓冲区,然后是服务器和日期头。这两个头文件的值分别取自version_string()和date_time_string()方法。如果服务器不打算使用send_header()方法发送任何其他头,则send_response()后面应该跟着end_headers()调用。
send_header(keyword, value)
将HTTP头添加到内部缓冲区,当调用end_headers()或flush_headers()时,该缓冲区将被写入输出流。关键字应该指定header关键字,value指定其值。注意,在send_header调用完成之后,必须调用end_headers()来完成操作。
send_response_only(code, message=None)
只发送响应头,当服务器将100个Continue响应发送到客户机时,将使用该响应头。头文件没有缓存并直接发送输出流。如果未指定消息,则发送与响应代码对应的HTTP消息。
end_headers()
将空行(指示响应中HTTP头的末尾)添加到头缓冲区并调用flush_headers()。
flush_headers()
最后将标头发送到输出流并刷新内部标头缓冲区。
log_request(code=’-’, size=’-’)
记录一个被接受的(成功的)请求。代码应该指定与响应相关联的数字HTTP代码。如果响应的大小可用,则应将其作为size参数传递。
log_error(…)
当一个请求不能被执行时,记录一个错误。默认情况下,它将消息传递给log_message(),因此它接受相同的参数(格式和附加值)。
log_message(format, …)
将任意消息记录到sys.stderr。这通常被覆盖以创建自定义错误日志记录机制。format参数是一个标准的printf样式的格式字符串,其中log_message()的附加参数用作格式化的输入。客户端ip地址和当前日期和时间是每个记录的消息的前缀。
version_string()
返回服务器软件的版本字符串。这是server_version和sys_version属性的组合。
date_time_string(timestamp=None)
返回服务器软件的版本字符串。这是server_version和sys_version属性的组合。返回时间戳给出的日期和时间(时间戳必须为None或time.time()返回的格式,该格式用于消息头。如果省略时间戳,则使用当前日期和时间。
结果看起来像’Sun, 06 november 1994 08:49:37 GMT’。
log_date_time_string()
返回用于日志记录的当前日期和时间。
address_string()
返回客户端地址。
SimpleHTTPRequestHandler
class http.server.SimpleHTTPRequestHandler(request, client_address, server, directory=None)
该类提供当前目录及以下目录中的文件,直接将目录结构映射到HTTP请求。
许多工作,比如解析请求,都是由基类BaseHTTPRequestHandler完成的。该类实现do_GET()和do_HEAD()函数。
以下定义为SimpleHTTPRequestHandler的类级属性:
server_version
这将是“SimpleHTTP/”+……version__,其中在模块级别定义了……version__。
extensions_map
将后缀映射到MIME类型的字典。默认值由一个空字符串表示,被认为是application/octe -stream。映射不区分大小写,因此应该只包含大小写较低的键。
directory
如果没有指定,要提供的目录是当前工作目录。
SimpleHTTPRequestHandler类定义了以下方法:
do_HEAD()
这个方法服务于“HEAD”请求类型:它发送它将为等效GET请求发送的头。有关可能的头的更完整的解释,请参见do_GET()方法。
do_GET()
通过将请求解释为相对于当前工作目录的路径,将请求映射到本地文件。
如果将请求映射到一个目录,则将检查目录中名为index.html或index.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:”报头。
然后跟随表示头文件末尾的空行,然后输出文件的内容。如果文件的MIME类型以text开头/文件以text模式打开;否则使用二进制模式。
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.sever 还可以直接使用 -m 转换解析器通过端口数字参数。类似于前面的例子,它提供了相对于当前目录的文件:
python -m http.server 8000
python -m http.server 8000 --bind 127.0.0.1
默认情况下,服务器使用当前目录。选项-d/——directory指定它应该提供文件的目录。例如,下面的命令使用一个特定的目录:
python -m http.server --directory /tmp/
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_directory路径下面的某个位置。
do_POST()
此方法提供“POST”请求类型,仅允许CGI脚本使用。错误501,“只能发布到CGI脚本”,是输出时试图发布到一个非CGI url。