代码阅读 - BaseHTTPServer.py

来源:互联网 发布:淘宝规则小卖家死 编辑:程序博客网 时间:2024/05/01 03:47

1.        BaseHTTPServer.py

平平无奇,看过SocketServer之后,只要了解HTTP协议就能看明白。

HTTPServer 继承自 SocketServer.TCPServer

BaseHTTPRequestHandler 继承自 SocketServer.StreamRequestHandler

1.1     HTTPServer

HTTP协议本身就是在TCP之上建立的应用层协议,所以不需要做太多的工作。这里的事项方法是将协议的解析等工作放到Handler类中,在Server类中仅仅覆盖了server_bind函数:

1.         首先调用TCPServer.server_bind

2.         然后通过 socket. socket.getsockname socket.getfqdn得到完整的主机名和端口。

1.2     HTTP协议回顾

HTTP请求数据流中的三个部分:

1.         第一行表示请求的类型路径,格式为 <command> <path> [<version>]

2.         可选的HEADERSHEADER之间用CRLFLF分割;

3.         可选的数据部分;数据和HEADER之间由一个空行分割。

HTTP相应数据流中的三个部分:

1.         第一行表示响应代码,格式为 <version> <response_code> [<responsestring>]

2.         可选的HEADERS

3.         数据部分;和HEADER之间由一个空行分割。

1.3     BaseHTTPRequestHandler

SocketServer.BaseRequestHandler的构造函数中,调用了三个方法:setup, handle, finish。其中handler用来处理请求,而且被实现为空函数。

SocketServer.StreamRequestHandler中,并没有对handle进行覆盖,而是覆盖setupsocket构造为输入和输出文件 rfile wfile

所以在BaseHTTPRequestHandler中,只需要覆盖handle,对客户端的请求进行处理。

1.3.1              handle方法

self.close_connection = 1

self.handle_one_request()

     while not self.close_connection:

         self.handle_one_request()

这里的关键是close_connection。主要是为了区分http request header中的 keep-alive

1.3.2              handle_one_request方法

rfile中读出一行;这一行就是command + path行;

如果读取成功,调用parse_request解析客户端的请求;将请求的操作保存在self.command;判断类是否具有do_command(如do_POST)方法,如果没有,发送501错误;如果有则使用getattr魔法得到方法并调用。

1.3.3              parse_request方法

解析从rfile中得到的那个command + path,没什么难度。

需要注意的是如果解析成功的话,会调用mimetools.Message的构造函数,生成一个类实例。这个构造函数需要rfile作为参数。构造过程其实也就是HEADERS的解析过程。

要具体研究一下这个类。

1.3.4              其他方法

send_response,用来发送HTTP响应的第一行;

send_header,发送一个HEADER

end_headers,发送一个空白行;

以及log函数和其它辅助函数。

1.4     总结

有了TCPServerStreamRequestHandler两个构造的非常好的基类,处理简单的HTTP请求并做出响应并不是难事。