python的SimpleHTTPServer do_GET和do_POST函数是如何工作的?



我创建了以下小HTTP服务器用于学习目的:

import SimpleHTTPServer
import SocketServer
class ServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def do_GET(self):
print(self.headers)
SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
def do_POST(self):
print(self.headers)
form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={'REQUEST_METHOD':'POST',
'CONTENT_TYPE':self.headers['Content-Type'],
def main():
port = 50738
Handler = ServerHandler(1000)
httpd = SocketServer.TCPServer(("192.168.X.Y", port), Handler)
print "serving at port", port
httpd.serve_forever()

if __name__ == "__main__":
main()

我的假设如下:

  • 我的类"ServerHandler"通过两个函数扩展了SimpleHTTPServer.SimpleHTTPRequestHandler类,即go_GET和do_POST
  • main(( 函数创建一个服务器处理程序对象和服务器套接字绑定到我的 I.P. 地址和所选端口,并调用一个函数无限期地服务/侦听。

旁白:通过查看 Python DOC https://docs.python.org/2/library/simplehttpserver.html 我知道 SimpleHTTPServer.SimpleHTTPRequestHandler 有一个名为 do_GET 的方法,我认为它被我的 ServerHandler 类中的do_GET覆盖了?

问题: 与do_GET和do_POST有关的引擎盖下发生了什么?是不是这样,一旦我们让这个服务器侦听指向特定 IP:PORT 的 HTTP"活动",它就会自动知道传入信号是 GET 还是 POST,一旦遇到,服务器就会调用我的do_GET或do_POST函数?

当您调用SocketServer.TCPServer时,您将Handler类指定为接收传入请求的类。

SimpleHTTPServer

模块为您提供的所有帮助都是提供基本的HTTP功能,但您可以自己编写所有这些功能。

因此,正如您所说,当您定义Handler时,您将继承SimpleHTTPRequestHandler类中的所有方法,但随后覆盖两个预定义的方法:do_GETdo_POST。您还可以重写类中的任何其他方法。

但是,如果不是在SimpleHTTPRequestHandler中定义的handle方法,则永远不会调用这些do_*方法,因为socketserver模块调用的是此函数。

因此,如果您只是继承socketserver.BaseRequestHandler,您将丢失所有功能,因为此类的handle()方法不执行任何操作:

class socketserver.BaseRequestHandler

handle()

此函数必须完成为 请求。默认实现不执行任何操作。多个实例 属性可供其使用;该请求可用作 自我请求;客户端地址为self.client_address;和 服务器实例作为 self.server,以防它需要访问每个服务器 信息。

因此,通过从SimpleHTTPServer模块导入SimpleHTTPRequestHandler,您可以立即获得 HTTP 服务器的基本功能。

所有这些功能都记录在这里,其中有一个重要的关于其handle方法:

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

handle()

调用 handle_one_request(( 一次(或者,如果持久调用( 多次启用连接以处理传入的 HTTP 请求。你永远不需要覆盖它;相反,实施 适当的 do_*(( 方法。

handle_one_request()

此方法将解析和调度请求 到适当的 do_*(( 方法。你永远不需要覆盖 它。

所以最后,在分解了socketserver.TCPServer将如何为你传递它的任何类调用handle()方法之后,我们看到SimpleHTTPRequestHandler如何实现它,将请求传递给适当的do_GETdo_POST或任何方法,具体取决于请求的标头。


如果您想了解如何自己实现这一点,请查看源代码,无论是在/usr/lib/pythonX.Y/http/server.py还是在 GitHub 上。

我们可以在那里看到他们的SimpleHTTPServer继承了什么BaseHTTPServer这是定义handle()handle_one_request()方法的地方:

因此,正如文档所述,handle只是将请求传递给handle_one_request,直到连接关闭:

def handle(self):
"""Handle multiple requests if necessary."""
self.close_connection = True
self.handle_one_request()
while not self.close_connection:
self.handle_one_request()

handle_one_request是调用do_*方法的地方:

def handle_one_request(self):
"""Handle a single HTTP request.
You normally don't need to override this method; see the class
__doc__ string for information on how to handle specific HTTP
commands such as GET and POST.
"""
try:
self.raw_requestline = self.rfile.readline(65537)
if len(self.raw_requestline) > 65536:
self.requestline = ''
self.request_version = ''
self.command = ''
self.send_error(HTTPStatus.REQUEST_URI_TOO_LONG)
return
if not self.raw_requestline:
self.close_connection = True
return
if not self.parse_request():
# An error code has been sent, just exit
return
mname = 'do_' + self.command   ## the name of the method is created
if not hasattr(self, mname):   ## checking that we have that method defined
self.send_error(
HTTPStatus.NOT_IMPLEMENTED,
"Unsupported method (%r)" % self.command)
return
method = getattr(self, mname)  ## getting that method
method()                       ## finally calling it
self.wfile.flush() #actually send the response if not already done.
except socket.timeout as e:
#a read or a write timed out.  Discard this connection
self.log_error("Request timed out: %r", e)
self.close_connection = True
return

(注意,我双重散列(##(我的评论以将它们与原作者的评论分开(

相关内容

  • 没有找到相关文章

最新更新