为了学习目的,我创建了以下小型 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()
我的假设如下:
旁白 :我通过查看 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_GET
和 do_POST
。您还可以覆盖类中的任何其他方法。
但是,如果不是 do_*
中定义的 handle
方法,这些 SimpleHTTPRequestHandler
方法将永远不会被调用,因为 socketserver
模块调用的是这个函数。
所以如果你只是继承 socketserver.BaseRequestHandler
,你会失去所有功能,因为这个类的 handle()
方法什么都不做:
...
因此,通过从 SimpleHTTPRequestHandler
模块导入 SimpleHTTPServer
,您可以立即获得 HTTP 服务器的基本功能。
所有这些功能都记录在案 here ,其 handle
方法有一个重要的部分:
handle_one_request()
...
所以最后,在分解 socketserver.TCPServer
如何为你传递的任何类调用 handle()
方法之后,我们看到 SimpleHTTPRequestHandler
如何实现这一点,将请求传递给适当的 do_GET
、 do_POST
或任何方法,具体取决于请求的 header 。
如果您想了解如何自己实现,请查看 /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
(注意,我对(
##
)我的评论进行了双重哈希处理,以将它们与原作者的评论分开)关于python - python 的 SimpleHTTPServer do_GET 和 do_POST 函数是如何工作的?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50944323/